linux/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2014-2016 Freescale Semiconductor Inc.
   3 * Copyright 2016 NXP
   4 * Copyright 2020 NXP
   5 */
   6
   7#include <linux/net_tstamp.h>
   8#include <linux/nospec.h>
   9
  10#include "dpni.h"       /* DPNI_LINK_OPT_* */
  11#include "dpaa2-eth.h"
  12
  13/* To be kept in sync with DPNI statistics */
  14static char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
  15        "[hw] rx frames",
  16        "[hw] rx bytes",
  17        "[hw] rx mcast frames",
  18        "[hw] rx mcast bytes",
  19        "[hw] rx bcast frames",
  20        "[hw] rx bcast bytes",
  21        "[hw] tx frames",
  22        "[hw] tx bytes",
  23        "[hw] tx mcast frames",
  24        "[hw] tx mcast bytes",
  25        "[hw] tx bcast frames",
  26        "[hw] tx bcast bytes",
  27        "[hw] rx filtered frames",
  28        "[hw] rx discarded frames",
  29        "[hw] rx nobuffer discards",
  30        "[hw] tx discarded frames",
  31        "[hw] tx confirmed frames",
  32        "[hw] tx dequeued bytes",
  33        "[hw] tx dequeued frames",
  34        "[hw] tx rejected bytes",
  35        "[hw] tx rejected frames",
  36        "[hw] tx pending frames",
  37};
  38
  39#define DPAA2_ETH_NUM_STATS     ARRAY_SIZE(dpaa2_ethtool_stats)
  40
  41static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
  42        /* per-cpu stats */
  43        "[drv] tx conf frames",
  44        "[drv] tx conf bytes",
  45        "[drv] tx sg frames",
  46        "[drv] tx sg bytes",
  47        "[drv] rx sg frames",
  48        "[drv] rx sg bytes",
  49        "[drv] tx converted sg frames",
  50        "[drv] tx converted sg bytes",
  51        "[drv] enqueue portal busy",
  52        /* Channel stats */
  53        "[drv] dequeue portal busy",
  54        "[drv] channel pull errors",
  55        "[drv] cdan",
  56        "[drv] xdp drop",
  57        "[drv] xdp tx",
  58        "[drv] xdp tx errors",
  59        "[drv] xdp redirect",
  60        /* FQ stats */
  61        "[qbman] rx pending frames",
  62        "[qbman] rx pending bytes",
  63        "[qbman] tx conf pending frames",
  64        "[qbman] tx conf pending bytes",
  65        "[qbman] buffer count",
  66};
  67
  68#define DPAA2_ETH_NUM_EXTRA_STATS       ARRAY_SIZE(dpaa2_ethtool_extras)
  69
  70static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
  71                                  struct ethtool_drvinfo *drvinfo)
  72{
  73        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  74
  75        strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  76
  77        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  78                 "%u.%u", priv->dpni_ver_major, priv->dpni_ver_minor);
  79
  80        strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
  81                sizeof(drvinfo->bus_info));
  82}
  83
  84static int dpaa2_eth_nway_reset(struct net_device *net_dev)
  85{
  86        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  87
  88        if (dpaa2_eth_is_type_phy(priv))
  89                return phylink_ethtool_nway_reset(priv->mac->phylink);
  90
  91        return -EOPNOTSUPP;
  92}
  93
  94static int
  95dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
  96                             struct ethtool_link_ksettings *link_settings)
  97{
  98        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  99
 100        if (dpaa2_eth_is_type_phy(priv))
 101                return phylink_ethtool_ksettings_get(priv->mac->phylink,
 102                                                     link_settings);
 103
 104        link_settings->base.autoneg = AUTONEG_DISABLE;
 105        if (!(priv->link_state.options & DPNI_LINK_OPT_HALF_DUPLEX))
 106                link_settings->base.duplex = DUPLEX_FULL;
 107        link_settings->base.speed = priv->link_state.rate;
 108
 109        return 0;
 110}
 111
 112static int
 113dpaa2_eth_set_link_ksettings(struct net_device *net_dev,
 114                             const struct ethtool_link_ksettings *link_settings)
 115{
 116        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 117
 118        if (!dpaa2_eth_is_type_phy(priv))
 119                return -ENOTSUPP;
 120
 121        return phylink_ethtool_ksettings_set(priv->mac->phylink, link_settings);
 122}
 123
 124static void dpaa2_eth_get_pauseparam(struct net_device *net_dev,
 125                                     struct ethtool_pauseparam *pause)
 126{
 127        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 128        u64 link_options = priv->link_state.options;
 129
 130        if (dpaa2_eth_is_type_phy(priv)) {
 131                phylink_ethtool_get_pauseparam(priv->mac->phylink, pause);
 132                return;
 133        }
 134
 135        pause->rx_pause = dpaa2_eth_rx_pause_enabled(link_options);
 136        pause->tx_pause = dpaa2_eth_tx_pause_enabled(link_options);
 137        pause->autoneg = AUTONEG_DISABLE;
 138}
 139
 140static int dpaa2_eth_set_pauseparam(struct net_device *net_dev,
 141                                    struct ethtool_pauseparam *pause)
 142{
 143        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 144        struct dpni_link_cfg cfg = {0};
 145        int err;
 146
 147        if (!dpaa2_eth_has_pause_support(priv)) {
 148                netdev_info(net_dev, "No pause frame support for DPNI version < %d.%d\n",
 149                            DPNI_PAUSE_VER_MAJOR, DPNI_PAUSE_VER_MINOR);
 150                return -EOPNOTSUPP;
 151        }
 152
 153        if (dpaa2_eth_is_type_phy(priv))
 154                return phylink_ethtool_set_pauseparam(priv->mac->phylink,
 155                                                      pause);
 156        if (pause->autoneg)
 157                return -EOPNOTSUPP;
 158
 159        cfg.rate = priv->link_state.rate;
 160        cfg.options = priv->link_state.options;
 161        if (pause->rx_pause)
 162                cfg.options |= DPNI_LINK_OPT_PAUSE;
 163        else
 164                cfg.options &= ~DPNI_LINK_OPT_PAUSE;
 165        if (!!pause->rx_pause ^ !!pause->tx_pause)
 166                cfg.options |= DPNI_LINK_OPT_ASYM_PAUSE;
 167        else
 168                cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
 169
 170        if (cfg.options == priv->link_state.options)
 171                return 0;
 172
 173        err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
 174        if (err) {
 175                netdev_err(net_dev, "dpni_set_link_state failed\n");
 176                return err;
 177        }
 178
 179        priv->link_state.options = cfg.options;
 180
 181        return 0;
 182}
 183
 184static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
 185                                  u8 *data)
 186{
 187        struct dpaa2_eth_priv *priv = netdev_priv(netdev);
 188        u8 *p = data;
 189        int i;
 190
 191        switch (stringset) {
 192        case ETH_SS_STATS:
 193                for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
 194                        strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
 195                        p += ETH_GSTRING_LEN;
 196                }
 197                for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
 198                        strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
 199                        p += ETH_GSTRING_LEN;
 200                }
 201                if (dpaa2_eth_has_mac(priv))
 202                        dpaa2_mac_get_strings(p);
 203                break;
 204        }
 205}
 206
 207static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)
 208{
 209        int num_ss_stats = DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
 210        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 211
 212        switch (sset) {
 213        case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
 214                if (dpaa2_eth_has_mac(priv))
 215                        num_ss_stats += dpaa2_mac_get_sset_count();
 216                return num_ss_stats;
 217        default:
 218                return -EOPNOTSUPP;
 219        }
 220}
 221
 222/** Fill in hardware counters, as returned by MC.
 223 */
 224static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
 225                                        struct ethtool_stats *stats,
 226                                        u64 *data)
 227{
 228        int i = 0;
 229        int j, k, err;
 230        int num_cnt;
 231        union dpni_statistics dpni_stats;
 232        u32 fcnt, bcnt;
 233        u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
 234        u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
 235        u32 buf_cnt;
 236        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 237        struct dpaa2_eth_drv_stats *extras;
 238        struct dpaa2_eth_ch_stats *ch_stats;
 239        int dpni_stats_page_size[DPNI_STATISTICS_CNT] = {
 240                sizeof(dpni_stats.page_0),
 241                sizeof(dpni_stats.page_1),
 242                sizeof(dpni_stats.page_2),
 243                sizeof(dpni_stats.page_3),
 244                sizeof(dpni_stats.page_4),
 245                sizeof(dpni_stats.page_5),
 246                sizeof(dpni_stats.page_6),
 247        };
 248
 249        memset(data, 0,
 250               sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
 251
 252        /* Print standard counters, from DPNI statistics */
 253        for (j = 0; j <= 6; j++) {
 254                /* We're not interested in pages 4 & 5 for now */
 255                if (j == 4 || j == 5)
 256                        continue;
 257                err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
 258                                          j, &dpni_stats);
 259                if (err == -EINVAL)
 260                        /* Older firmware versions don't support all pages */
 261                        memset(&dpni_stats, 0, sizeof(dpni_stats));
 262                else if (err)
 263                        netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j);
 264
 265                num_cnt = dpni_stats_page_size[j] / sizeof(u64);
 266                for (k = 0; k < num_cnt; k++)
 267                        *(data + i++) = dpni_stats.raw.counter[k];
 268        }
 269
 270        /* Print per-cpu extra stats */
 271        for_each_online_cpu(k) {
 272                extras = per_cpu_ptr(priv->percpu_extras, k);
 273                for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
 274                        *((__u64 *)data + i + j) += *((__u64 *)extras + j);
 275        }
 276        i += j;
 277
 278        /* Per-channel stats */
 279        for (k = 0; k < priv->num_channels; k++) {
 280                ch_stats = &priv->channel[k]->stats;
 281                for (j = 0; j < sizeof(*ch_stats) / sizeof(__u64) - 1; j++)
 282                        *((__u64 *)data + i + j) += *((__u64 *)ch_stats + j);
 283        }
 284        i += j;
 285
 286        for (j = 0; j < priv->num_fqs; j++) {
 287                /* Print FQ instantaneous counts */
 288                err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
 289                                              &fcnt, &bcnt);
 290                if (err) {
 291                        netdev_warn(net_dev, "FQ query error %d", err);
 292                        return;
 293                }
 294
 295                if (priv->fq[j].type == DPAA2_TX_CONF_FQ) {
 296                        fcnt_tx_total += fcnt;
 297                        bcnt_tx_total += bcnt;
 298                } else {
 299                        fcnt_rx_total += fcnt;
 300                        bcnt_rx_total += bcnt;
 301                }
 302        }
 303
 304        *(data + i++) = fcnt_rx_total;
 305        *(data + i++) = bcnt_rx_total;
 306        *(data + i++) = fcnt_tx_total;
 307        *(data + i++) = bcnt_tx_total;
 308
 309        err = dpaa2_io_query_bp_count(NULL, priv->bpid, &buf_cnt);
 310        if (err) {
 311                netdev_warn(net_dev, "Buffer count query error %d\n", err);
 312                return;
 313        }
 314        *(data + i++) = buf_cnt;
 315
 316        if (dpaa2_eth_has_mac(priv))
 317                dpaa2_mac_get_ethtool_stats(priv->mac, data + i);
 318}
 319
 320static int dpaa2_eth_prep_eth_rule(struct ethhdr *eth_value, struct ethhdr *eth_mask,
 321                                   void *key, void *mask, u64 *fields)
 322{
 323        int off;
 324
 325        if (eth_mask->h_proto) {
 326                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 327                *(__be16 *)(key + off) = eth_value->h_proto;
 328                *(__be16 *)(mask + off) = eth_mask->h_proto;
 329                *fields |= DPAA2_ETH_DIST_ETHTYPE;
 330        }
 331
 332        if (!is_zero_ether_addr(eth_mask->h_source)) {
 333                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_SA);
 334                ether_addr_copy(key + off, eth_value->h_source);
 335                ether_addr_copy(mask + off, eth_mask->h_source);
 336                *fields |= DPAA2_ETH_DIST_ETHSRC;
 337        }
 338
 339        if (!is_zero_ether_addr(eth_mask->h_dest)) {
 340                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
 341                ether_addr_copy(key + off, eth_value->h_dest);
 342                ether_addr_copy(mask + off, eth_mask->h_dest);
 343                *fields |= DPAA2_ETH_DIST_ETHDST;
 344        }
 345
 346        return 0;
 347}
 348
 349static int dpaa2_eth_prep_uip_rule(struct ethtool_usrip4_spec *uip_value,
 350                                   struct ethtool_usrip4_spec *uip_mask,
 351                                   void *key, void *mask, u64 *fields)
 352{
 353        int off;
 354        u32 tmp_value, tmp_mask;
 355
 356        if (uip_mask->tos || uip_mask->ip_ver)
 357                return -EOPNOTSUPP;
 358
 359        if (uip_mask->ip4src) {
 360                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
 361                *(__be32 *)(key + off) = uip_value->ip4src;
 362                *(__be32 *)(mask + off) = uip_mask->ip4src;
 363                *fields |= DPAA2_ETH_DIST_IPSRC;
 364        }
 365
 366        if (uip_mask->ip4dst) {
 367                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
 368                *(__be32 *)(key + off) = uip_value->ip4dst;
 369                *(__be32 *)(mask + off) = uip_mask->ip4dst;
 370                *fields |= DPAA2_ETH_DIST_IPDST;
 371        }
 372
 373        if (uip_mask->proto) {
 374                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
 375                *(u8 *)(key + off) = uip_value->proto;
 376                *(u8 *)(mask + off) = uip_mask->proto;
 377                *fields |= DPAA2_ETH_DIST_IPPROTO;
 378        }
 379
 380        if (uip_mask->l4_4_bytes) {
 381                tmp_value = be32_to_cpu(uip_value->l4_4_bytes);
 382                tmp_mask = be32_to_cpu(uip_mask->l4_4_bytes);
 383
 384                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
 385                *(__be16 *)(key + off) = htons(tmp_value >> 16);
 386                *(__be16 *)(mask + off) = htons(tmp_mask >> 16);
 387                *fields |= DPAA2_ETH_DIST_L4SRC;
 388
 389                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
 390                *(__be16 *)(key + off) = htons(tmp_value & 0xFFFF);
 391                *(__be16 *)(mask + off) = htons(tmp_mask & 0xFFFF);
 392                *fields |= DPAA2_ETH_DIST_L4DST;
 393        }
 394
 395        /* Only apply the rule for IPv4 frames */
 396        off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 397        *(__be16 *)(key + off) = htons(ETH_P_IP);
 398        *(__be16 *)(mask + off) = htons(0xFFFF);
 399        *fields |= DPAA2_ETH_DIST_ETHTYPE;
 400
 401        return 0;
 402}
 403
 404static int dpaa2_eth_prep_l4_rule(struct ethtool_tcpip4_spec *l4_value,
 405                                  struct ethtool_tcpip4_spec *l4_mask,
 406                                  void *key, void *mask, u8 l4_proto, u64 *fields)
 407{
 408        int off;
 409
 410        if (l4_mask->tos)
 411                return -EOPNOTSUPP;
 412
 413        if (l4_mask->ip4src) {
 414                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
 415                *(__be32 *)(key + off) = l4_value->ip4src;
 416                *(__be32 *)(mask + off) = l4_mask->ip4src;
 417                *fields |= DPAA2_ETH_DIST_IPSRC;
 418        }
 419
 420        if (l4_mask->ip4dst) {
 421                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
 422                *(__be32 *)(key + off) = l4_value->ip4dst;
 423                *(__be32 *)(mask + off) = l4_mask->ip4dst;
 424                *fields |= DPAA2_ETH_DIST_IPDST;
 425        }
 426
 427        if (l4_mask->psrc) {
 428                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
 429                *(__be16 *)(key + off) = l4_value->psrc;
 430                *(__be16 *)(mask + off) = l4_mask->psrc;
 431                *fields |= DPAA2_ETH_DIST_L4SRC;
 432        }
 433
 434        if (l4_mask->pdst) {
 435                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
 436                *(__be16 *)(key + off) = l4_value->pdst;
 437                *(__be16 *)(mask + off) = l4_mask->pdst;
 438                *fields |= DPAA2_ETH_DIST_L4DST;
 439        }
 440
 441        /* Only apply the rule for IPv4 frames with the specified L4 proto */
 442        off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 443        *(__be16 *)(key + off) = htons(ETH_P_IP);
 444        *(__be16 *)(mask + off) = htons(0xFFFF);
 445        *fields |= DPAA2_ETH_DIST_ETHTYPE;
 446
 447        off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
 448        *(u8 *)(key + off) = l4_proto;
 449        *(u8 *)(mask + off) = 0xFF;
 450        *fields |= DPAA2_ETH_DIST_IPPROTO;
 451
 452        return 0;
 453}
 454
 455static int dpaa2_eth_prep_ext_rule(struct ethtool_flow_ext *ext_value,
 456                                   struct ethtool_flow_ext *ext_mask,
 457                                   void *key, void *mask, u64 *fields)
 458{
 459        int off;
 460
 461        if (ext_mask->vlan_etype)
 462                return -EOPNOTSUPP;
 463
 464        if (ext_mask->vlan_tci) {
 465                off = dpaa2_eth_cls_fld_off(NET_PROT_VLAN, NH_FLD_VLAN_TCI);
 466                *(__be16 *)(key + off) = ext_value->vlan_tci;
 467                *(__be16 *)(mask + off) = ext_mask->vlan_tci;
 468                *fields |= DPAA2_ETH_DIST_VLAN;
 469        }
 470
 471        return 0;
 472}
 473
 474static int dpaa2_eth_prep_mac_ext_rule(struct ethtool_flow_ext *ext_value,
 475                                       struct ethtool_flow_ext *ext_mask,
 476                                       void *key, void *mask, u64 *fields)
 477{
 478        int off;
 479
 480        if (!is_zero_ether_addr(ext_mask->h_dest)) {
 481                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
 482                ether_addr_copy(key + off, ext_value->h_dest);
 483                ether_addr_copy(mask + off, ext_mask->h_dest);
 484                *fields |= DPAA2_ETH_DIST_ETHDST;
 485        }
 486
 487        return 0;
 488}
 489
 490static int dpaa2_eth_prep_cls_rule(struct ethtool_rx_flow_spec *fs, void *key,
 491                                   void *mask, u64 *fields)
 492{
 493        int err;
 494
 495        switch (fs->flow_type & 0xFF) {
 496        case ETHER_FLOW:
 497                err = dpaa2_eth_prep_eth_rule(&fs->h_u.ether_spec, &fs->m_u.ether_spec,
 498                                              key, mask, fields);
 499                break;
 500        case IP_USER_FLOW:
 501                err = dpaa2_eth_prep_uip_rule(&fs->h_u.usr_ip4_spec,
 502                                              &fs->m_u.usr_ip4_spec, key, mask, fields);
 503                break;
 504        case TCP_V4_FLOW:
 505                err = dpaa2_eth_prep_l4_rule(&fs->h_u.tcp_ip4_spec, &fs->m_u.tcp_ip4_spec,
 506                                             key, mask, IPPROTO_TCP, fields);
 507                break;
 508        case UDP_V4_FLOW:
 509                err = dpaa2_eth_prep_l4_rule(&fs->h_u.udp_ip4_spec, &fs->m_u.udp_ip4_spec,
 510                                             key, mask, IPPROTO_UDP, fields);
 511                break;
 512        case SCTP_V4_FLOW:
 513                err = dpaa2_eth_prep_l4_rule(&fs->h_u.sctp_ip4_spec,
 514                                             &fs->m_u.sctp_ip4_spec, key, mask,
 515                                             IPPROTO_SCTP, fields);
 516                break;
 517        default:
 518                return -EOPNOTSUPP;
 519        }
 520
 521        if (err)
 522                return err;
 523
 524        if (fs->flow_type & FLOW_EXT) {
 525                err = dpaa2_eth_prep_ext_rule(&fs->h_ext, &fs->m_ext, key, mask, fields);
 526                if (err)
 527                        return err;
 528        }
 529
 530        if (fs->flow_type & FLOW_MAC_EXT) {
 531                err = dpaa2_eth_prep_mac_ext_rule(&fs->h_ext, &fs->m_ext, key,
 532                                                  mask, fields);
 533                if (err)
 534                        return err;
 535        }
 536
 537        return 0;
 538}
 539
 540static int dpaa2_eth_do_cls_rule(struct net_device *net_dev,
 541                                 struct ethtool_rx_flow_spec *fs,
 542                                 bool add)
 543{
 544        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 545        struct device *dev = net_dev->dev.parent;
 546        struct dpni_rule_cfg rule_cfg = { 0 };
 547        struct dpni_fs_action_cfg fs_act = { 0 };
 548        dma_addr_t key_iova;
 549        u64 fields = 0;
 550        void *key_buf;
 551        int i, err;
 552
 553        if (fs->ring_cookie != RX_CLS_FLOW_DISC &&
 554            fs->ring_cookie >= dpaa2_eth_queue_count(priv))
 555                return -EINVAL;
 556
 557        rule_cfg.key_size = dpaa2_eth_cls_key_size(DPAA2_ETH_DIST_ALL);
 558
 559        /* allocate twice the key size, for the actual key and for mask */
 560        key_buf = kzalloc(rule_cfg.key_size * 2, GFP_KERNEL);
 561        if (!key_buf)
 562                return -ENOMEM;
 563
 564        /* Fill the key and mask memory areas */
 565        err = dpaa2_eth_prep_cls_rule(fs, key_buf, key_buf + rule_cfg.key_size, &fields);
 566        if (err)
 567                goto free_mem;
 568
 569        if (!dpaa2_eth_fs_mask_enabled(priv)) {
 570                /* Masking allows us to configure a maximal key during init and
 571                 * use it for all flow steering rules. Without it, we include
 572                 * in the key only the fields actually used, so we need to
 573                 * extract the others from the final key buffer.
 574                 *
 575                 * Program the FS key if needed, or return error if previously
 576                 * set key can't be used for the current rule. User needs to
 577                 * delete existing rules in this case to allow for the new one.
 578                 */
 579                if (!priv->rx_cls_fields) {
 580                        err = dpaa2_eth_set_cls(net_dev, fields);
 581                        if (err)
 582                                goto free_mem;
 583
 584                        priv->rx_cls_fields = fields;
 585                } else if (priv->rx_cls_fields != fields) {
 586                        netdev_err(net_dev, "No support for multiple FS keys, need to delete existing rules\n");
 587                        err = -EOPNOTSUPP;
 588                        goto free_mem;
 589                }
 590
 591                dpaa2_eth_cls_trim_rule(key_buf, fields);
 592                rule_cfg.key_size = dpaa2_eth_cls_key_size(fields);
 593        }
 594
 595        key_iova = dma_map_single(dev, key_buf, rule_cfg.key_size * 2,
 596                                  DMA_TO_DEVICE);
 597        if (dma_mapping_error(dev, key_iova)) {
 598                err = -ENOMEM;
 599                goto free_mem;
 600        }
 601
 602        rule_cfg.key_iova = key_iova;
 603        if (dpaa2_eth_fs_mask_enabled(priv))
 604                rule_cfg.mask_iova = key_iova + rule_cfg.key_size;
 605
 606        if (add) {
 607                if (fs->ring_cookie == RX_CLS_FLOW_DISC)
 608                        fs_act.options |= DPNI_FS_OPT_DISCARD;
 609                else
 610                        fs_act.flow_id = fs->ring_cookie;
 611        }
 612        for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
 613                if (add)
 614                        err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
 615                                                i, fs->location, &rule_cfg,
 616                                                &fs_act);
 617                else
 618                        err = dpni_remove_fs_entry(priv->mc_io, 0,
 619                                                   priv->mc_token, i,
 620                                                   &rule_cfg);
 621                if (err || priv->dpni_attrs.options & DPNI_OPT_SHARED_FS)
 622                        break;
 623        }
 624
 625        dma_unmap_single(dev, key_iova, rule_cfg.key_size * 2, DMA_TO_DEVICE);
 626
 627free_mem:
 628        kfree(key_buf);
 629
 630        return err;
 631}
 632
 633static int dpaa2_eth_num_cls_rules(struct dpaa2_eth_priv *priv)
 634{
 635        int i, rules = 0;
 636
 637        for (i = 0; i < dpaa2_eth_fs_count(priv); i++)
 638                if (priv->cls_rules[i].in_use)
 639                        rules++;
 640
 641        return rules;
 642}
 643
 644static int dpaa2_eth_update_cls_rule(struct net_device *net_dev,
 645                                     struct ethtool_rx_flow_spec *new_fs,
 646                                     unsigned int location)
 647{
 648        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 649        struct dpaa2_eth_cls_rule *rule;
 650        int err = -EINVAL;
 651
 652        if (!priv->rx_cls_enabled)
 653                return -EOPNOTSUPP;
 654
 655        if (location >= dpaa2_eth_fs_count(priv))
 656                return -EINVAL;
 657
 658        rule = &priv->cls_rules[location];
 659
 660        /* If a rule is present at the specified location, delete it. */
 661        if (rule->in_use) {
 662                err = dpaa2_eth_do_cls_rule(net_dev, &rule->fs, false);
 663                if (err)
 664                        return err;
 665
 666                rule->in_use = 0;
 667
 668                if (!dpaa2_eth_fs_mask_enabled(priv) &&
 669                    !dpaa2_eth_num_cls_rules(priv))
 670                        priv->rx_cls_fields = 0;
 671        }
 672
 673        /* If no new entry to add, return here */
 674        if (!new_fs)
 675                return err;
 676
 677        err = dpaa2_eth_do_cls_rule(net_dev, new_fs, true);
 678        if (err)
 679                return err;
 680
 681        rule->in_use = 1;
 682        rule->fs = *new_fs;
 683
 684        return 0;
 685}
 686
 687static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
 688                               struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
 689{
 690        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 691        int max_rules = dpaa2_eth_fs_count(priv);
 692        int i, j = 0;
 693
 694        switch (rxnfc->cmd) {
 695        case ETHTOOL_GRXFH:
 696                /* we purposely ignore cmd->flow_type for now, because the
 697                 * classifier only supports a single set of fields for all
 698                 * protocols
 699                 */
 700                rxnfc->data = priv->rx_hash_fields;
 701                break;
 702        case ETHTOOL_GRXRINGS:
 703                rxnfc->data = dpaa2_eth_queue_count(priv);
 704                break;
 705        case ETHTOOL_GRXCLSRLCNT:
 706                rxnfc->rule_cnt = 0;
 707                rxnfc->rule_cnt = dpaa2_eth_num_cls_rules(priv);
 708                rxnfc->data = max_rules;
 709                break;
 710        case ETHTOOL_GRXCLSRULE:
 711                if (rxnfc->fs.location >= max_rules)
 712                        return -EINVAL;
 713                rxnfc->fs.location = array_index_nospec(rxnfc->fs.location,
 714                                                        max_rules);
 715                if (!priv->cls_rules[rxnfc->fs.location].in_use)
 716                        return -EINVAL;
 717                rxnfc->fs = priv->cls_rules[rxnfc->fs.location].fs;
 718                break;
 719        case ETHTOOL_GRXCLSRLALL:
 720                for (i = 0; i < max_rules; i++) {
 721                        if (!priv->cls_rules[i].in_use)
 722                                continue;
 723                        if (j == rxnfc->rule_cnt)
 724                                return -EMSGSIZE;
 725                        rule_locs[j++] = i;
 726                }
 727                rxnfc->rule_cnt = j;
 728                rxnfc->data = max_rules;
 729                break;
 730        default:
 731                return -EOPNOTSUPP;
 732        }
 733
 734        return 0;
 735}
 736
 737static int dpaa2_eth_set_rxnfc(struct net_device *net_dev,
 738                               struct ethtool_rxnfc *rxnfc)
 739{
 740        int err = 0;
 741
 742        switch (rxnfc->cmd) {
 743        case ETHTOOL_SRXFH:
 744                if ((rxnfc->data & DPAA2_RXH_SUPPORTED) != rxnfc->data)
 745                        return -EOPNOTSUPP;
 746                err = dpaa2_eth_set_hash(net_dev, rxnfc->data);
 747                break;
 748        case ETHTOOL_SRXCLSRLINS:
 749                err = dpaa2_eth_update_cls_rule(net_dev, &rxnfc->fs, rxnfc->fs.location);
 750                break;
 751        case ETHTOOL_SRXCLSRLDEL:
 752                err = dpaa2_eth_update_cls_rule(net_dev, NULL, rxnfc->fs.location);
 753                break;
 754        default:
 755                err = -EOPNOTSUPP;
 756        }
 757
 758        return err;
 759}
 760
 761int dpaa2_phc_index = -1;
 762EXPORT_SYMBOL(dpaa2_phc_index);
 763
 764static int dpaa2_eth_get_ts_info(struct net_device *dev,
 765                                 struct ethtool_ts_info *info)
 766{
 767        if (!dpaa2_ptp)
 768                return ethtool_op_get_ts_info(dev, info);
 769
 770        info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
 771                                SOF_TIMESTAMPING_RX_HARDWARE |
 772                                SOF_TIMESTAMPING_RAW_HARDWARE;
 773
 774        info->phc_index = dpaa2_phc_index;
 775
 776        info->tx_types = (1 << HWTSTAMP_TX_OFF) |
 777                         (1 << HWTSTAMP_TX_ON) |
 778                         (1 << HWTSTAMP_TX_ONESTEP_SYNC);
 779
 780        info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
 781                           (1 << HWTSTAMP_FILTER_ALL);
 782        return 0;
 783}
 784
 785static int dpaa2_eth_get_tunable(struct net_device *net_dev,
 786                                 const struct ethtool_tunable *tuna,
 787                                 void *data)
 788{
 789        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 790        int err = 0;
 791
 792        switch (tuna->id) {
 793        case ETHTOOL_RX_COPYBREAK:
 794                *(u32 *)data = priv->rx_copybreak;
 795                break;
 796        default:
 797                err = -EOPNOTSUPP;
 798                break;
 799        }
 800
 801        return err;
 802}
 803
 804static int dpaa2_eth_set_tunable(struct net_device *net_dev,
 805                                 const struct ethtool_tunable *tuna,
 806                                 const void *data)
 807{
 808        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 809        int err = 0;
 810
 811        switch (tuna->id) {
 812        case ETHTOOL_RX_COPYBREAK:
 813                priv->rx_copybreak = *(u32 *)data;
 814                break;
 815        default:
 816                err = -EOPNOTSUPP;
 817                break;
 818        }
 819
 820        return err;
 821}
 822
 823const struct ethtool_ops dpaa2_ethtool_ops = {
 824        .get_drvinfo = dpaa2_eth_get_drvinfo,
 825        .nway_reset = dpaa2_eth_nway_reset,
 826        .get_link = ethtool_op_get_link,
 827        .get_link_ksettings = dpaa2_eth_get_link_ksettings,
 828        .set_link_ksettings = dpaa2_eth_set_link_ksettings,
 829        .get_pauseparam = dpaa2_eth_get_pauseparam,
 830        .set_pauseparam = dpaa2_eth_set_pauseparam,
 831        .get_sset_count = dpaa2_eth_get_sset_count,
 832        .get_ethtool_stats = dpaa2_eth_get_ethtool_stats,
 833        .get_strings = dpaa2_eth_get_strings,
 834        .get_rxnfc = dpaa2_eth_get_rxnfc,
 835        .set_rxnfc = dpaa2_eth_set_rxnfc,
 836        .get_ts_info = dpaa2_eth_get_ts_info,
 837        .get_tunable = dpaa2_eth_get_tunable,
 838        .set_tunable = dpaa2_eth_set_tunable,
 839};
 840