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 */
   5
   6#include <linux/net_tstamp.h>
   7
   8#include "dpni.h"       /* DPNI_LINK_OPT_* */
   9#include "dpaa2-eth.h"
  10
  11/* To be kept in sync with DPNI statistics */
  12static char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
  13        "[hw] rx frames",
  14        "[hw] rx bytes",
  15        "[hw] rx mcast frames",
  16        "[hw] rx mcast bytes",
  17        "[hw] rx bcast frames",
  18        "[hw] rx bcast bytes",
  19        "[hw] tx frames",
  20        "[hw] tx bytes",
  21        "[hw] tx mcast frames",
  22        "[hw] tx mcast bytes",
  23        "[hw] tx bcast frames",
  24        "[hw] tx bcast bytes",
  25        "[hw] rx filtered frames",
  26        "[hw] rx discarded frames",
  27        "[hw] rx nobuffer discards",
  28        "[hw] tx discarded frames",
  29        "[hw] tx confirmed frames",
  30};
  31
  32#define DPAA2_ETH_NUM_STATS     ARRAY_SIZE(dpaa2_ethtool_stats)
  33
  34static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
  35        /* per-cpu stats */
  36        "[drv] tx conf frames",
  37        "[drv] tx conf bytes",
  38        "[drv] tx sg frames",
  39        "[drv] tx sg bytes",
  40        "[drv] tx realloc frames",
  41        "[drv] rx sg frames",
  42        "[drv] rx sg bytes",
  43        "[drv] enqueue portal busy",
  44        /* Channel stats */
  45        "[drv] dequeue portal busy",
  46        "[drv] channel pull errors",
  47        "[drv] cdan",
  48        "[drv] xdp drop",
  49        "[drv] xdp tx",
  50        "[drv] xdp tx errors",
  51        /* FQ stats */
  52        "[qbman] rx pending frames",
  53        "[qbman] rx pending bytes",
  54        "[qbman] tx conf pending frames",
  55        "[qbman] tx conf pending bytes",
  56        "[qbman] buffer count",
  57};
  58
  59#define DPAA2_ETH_NUM_EXTRA_STATS       ARRAY_SIZE(dpaa2_ethtool_extras)
  60
  61static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
  62                                  struct ethtool_drvinfo *drvinfo)
  63{
  64        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  65
  66        strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  67
  68        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  69                 "%u.%u", priv->dpni_ver_major, priv->dpni_ver_minor);
  70
  71        strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
  72                sizeof(drvinfo->bus_info));
  73}
  74
  75static int
  76dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
  77                             struct ethtool_link_ksettings *link_settings)
  78{
  79        struct dpni_link_state state = {0};
  80        int err = 0;
  81        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  82
  83        err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  84        if (err) {
  85                netdev_err(net_dev, "ERROR %d getting link state\n", err);
  86                goto out;
  87        }
  88
  89        /* At the moment, we have no way of interrogating the DPMAC
  90         * from the DPNI side - and for that matter there may exist
  91         * no DPMAC at all. So for now we just don't report anything
  92         * beyond the DPNI attributes.
  93         */
  94        if (state.options & DPNI_LINK_OPT_AUTONEG)
  95                link_settings->base.autoneg = AUTONEG_ENABLE;
  96        if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX))
  97                link_settings->base.duplex = DUPLEX_FULL;
  98        link_settings->base.speed = state.rate;
  99
 100out:
 101        return err;
 102}
 103
 104#define DPNI_DYNAMIC_LINK_SET_VER_MAJOR         7
 105#define DPNI_DYNAMIC_LINK_SET_VER_MINOR         1
 106static int
 107dpaa2_eth_set_link_ksettings(struct net_device *net_dev,
 108                             const struct ethtool_link_ksettings *link_settings)
 109{
 110        struct dpni_link_cfg cfg = {0};
 111        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 112        int err = 0;
 113
 114        /* If using an older MC version, the DPNI must be down
 115         * in order to be able to change link settings. Taking steps to let
 116         * the user know that.
 117         */
 118        if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_DYNAMIC_LINK_SET_VER_MAJOR,
 119                                   DPNI_DYNAMIC_LINK_SET_VER_MINOR) < 0) {
 120                if (netif_running(net_dev)) {
 121                        netdev_info(net_dev, "Interface must be brought down first.\n");
 122                        return -EACCES;
 123                }
 124        }
 125
 126        cfg.rate = link_settings->base.speed;
 127        if (link_settings->base.autoneg == AUTONEG_ENABLE)
 128                cfg.options |= DPNI_LINK_OPT_AUTONEG;
 129        else
 130                cfg.options &= ~DPNI_LINK_OPT_AUTONEG;
 131        if (link_settings->base.duplex  == DUPLEX_HALF)
 132                cfg.options |= DPNI_LINK_OPT_HALF_DUPLEX;
 133        else
 134                cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX;
 135
 136        err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
 137        if (err)
 138                /* ethtool will be loud enough if we return an error; no point
 139                 * in putting our own error message on the console by default
 140                 */
 141                netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err);
 142
 143        return err;
 144}
 145
 146static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
 147                                  u8 *data)
 148{
 149        u8 *p = data;
 150        int i;
 151
 152        switch (stringset) {
 153        case ETH_SS_STATS:
 154                for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
 155                        strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
 156                        p += ETH_GSTRING_LEN;
 157                }
 158                for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
 159                        strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
 160                        p += ETH_GSTRING_LEN;
 161                }
 162                break;
 163        }
 164}
 165
 166static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)
 167{
 168        switch (sset) {
 169        case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
 170                return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
 171        default:
 172                return -EOPNOTSUPP;
 173        }
 174}
 175
 176/** Fill in hardware counters, as returned by MC.
 177 */
 178static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
 179                                        struct ethtool_stats *stats,
 180                                        u64 *data)
 181{
 182        int i = 0;
 183        int j, k, err;
 184        int num_cnt;
 185        union dpni_statistics dpni_stats;
 186        u32 fcnt, bcnt;
 187        u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
 188        u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
 189        u32 buf_cnt;
 190        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 191        struct dpaa2_eth_drv_stats *extras;
 192        struct dpaa2_eth_ch_stats *ch_stats;
 193
 194        memset(data, 0,
 195               sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
 196
 197        /* Print standard counters, from DPNI statistics */
 198        for (j = 0; j <= 2; j++) {
 199                err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
 200                                          j, &dpni_stats);
 201                if (err != 0)
 202                        netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j);
 203                switch (j) {
 204                case 0:
 205                        num_cnt = sizeof(dpni_stats.page_0) / sizeof(u64);
 206                        break;
 207                case 1:
 208                        num_cnt = sizeof(dpni_stats.page_1) / sizeof(u64);
 209                        break;
 210                case 2:
 211                        num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64);
 212                        break;
 213                }
 214                for (k = 0; k < num_cnt; k++)
 215                        *(data + i++) = dpni_stats.raw.counter[k];
 216        }
 217
 218        /* Print per-cpu extra stats */
 219        for_each_online_cpu(k) {
 220                extras = per_cpu_ptr(priv->percpu_extras, k);
 221                for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
 222                        *((__u64 *)data + i + j) += *((__u64 *)extras + j);
 223        }
 224        i += j;
 225
 226        /* Per-channel stats */
 227        for (k = 0; k < priv->num_channels; k++) {
 228                ch_stats = &priv->channel[k]->stats;
 229                for (j = 0; j < sizeof(*ch_stats) / sizeof(__u64); j++)
 230                        *((__u64 *)data + i + j) += *((__u64 *)ch_stats + j);
 231        }
 232        i += j;
 233
 234        for (j = 0; j < priv->num_fqs; j++) {
 235                /* Print FQ instantaneous counts */
 236                err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
 237                                              &fcnt, &bcnt);
 238                if (err) {
 239                        netdev_warn(net_dev, "FQ query error %d", err);
 240                        return;
 241                }
 242
 243                if (priv->fq[j].type == DPAA2_TX_CONF_FQ) {
 244                        fcnt_tx_total += fcnt;
 245                        bcnt_tx_total += bcnt;
 246                } else {
 247                        fcnt_rx_total += fcnt;
 248                        bcnt_rx_total += bcnt;
 249                }
 250        }
 251
 252        *(data + i++) = fcnt_rx_total;
 253        *(data + i++) = bcnt_rx_total;
 254        *(data + i++) = fcnt_tx_total;
 255        *(data + i++) = bcnt_tx_total;
 256
 257        err = dpaa2_io_query_bp_count(NULL, priv->bpid, &buf_cnt);
 258        if (err) {
 259                netdev_warn(net_dev, "Buffer count query error %d\n", err);
 260                return;
 261        }
 262        *(data + i++) = buf_cnt;
 263}
 264
 265static int prep_eth_rule(struct ethhdr *eth_value, struct ethhdr *eth_mask,
 266                         void *key, void *mask)
 267{
 268        int off;
 269
 270        if (eth_mask->h_proto) {
 271                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 272                *(__be16 *)(key + off) = eth_value->h_proto;
 273                *(__be16 *)(mask + off) = eth_mask->h_proto;
 274        }
 275
 276        if (!is_zero_ether_addr(eth_mask->h_source)) {
 277                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_SA);
 278                ether_addr_copy(key + off, eth_value->h_source);
 279                ether_addr_copy(mask + off, eth_mask->h_source);
 280        }
 281
 282        if (!is_zero_ether_addr(eth_mask->h_dest)) {
 283                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
 284                ether_addr_copy(key + off, eth_value->h_dest);
 285                ether_addr_copy(mask + off, eth_mask->h_dest);
 286        }
 287
 288        return 0;
 289}
 290
 291static int prep_uip_rule(struct ethtool_usrip4_spec *uip_value,
 292                         struct ethtool_usrip4_spec *uip_mask,
 293                         void *key, void *mask)
 294{
 295        int off;
 296        u32 tmp_value, tmp_mask;
 297
 298        if (uip_mask->tos || uip_mask->ip_ver)
 299                return -EOPNOTSUPP;
 300
 301        if (uip_mask->ip4src) {
 302                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
 303                *(__be32 *)(key + off) = uip_value->ip4src;
 304                *(__be32 *)(mask + off) = uip_mask->ip4src;
 305        }
 306
 307        if (uip_mask->ip4dst) {
 308                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
 309                *(__be32 *)(key + off) = uip_value->ip4dst;
 310                *(__be32 *)(mask + off) = uip_mask->ip4dst;
 311        }
 312
 313        if (uip_mask->proto) {
 314                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
 315                *(u8 *)(key + off) = uip_value->proto;
 316                *(u8 *)(mask + off) = uip_mask->proto;
 317        }
 318
 319        if (uip_mask->l4_4_bytes) {
 320                tmp_value = be32_to_cpu(uip_value->l4_4_bytes);
 321                tmp_mask = be32_to_cpu(uip_mask->l4_4_bytes);
 322
 323                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
 324                *(__be16 *)(key + off) = htons(tmp_value >> 16);
 325                *(__be16 *)(mask + off) = htons(tmp_mask >> 16);
 326
 327                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
 328                *(__be16 *)(key + off) = htons(tmp_value & 0xFFFF);
 329                *(__be16 *)(mask + off) = htons(tmp_mask & 0xFFFF);
 330        }
 331
 332        /* Only apply the rule for IPv4 frames */
 333        off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 334        *(__be16 *)(key + off) = htons(ETH_P_IP);
 335        *(__be16 *)(mask + off) = htons(0xFFFF);
 336
 337        return 0;
 338}
 339
 340static int prep_l4_rule(struct ethtool_tcpip4_spec *l4_value,
 341                        struct ethtool_tcpip4_spec *l4_mask,
 342                        void *key, void *mask, u8 l4_proto)
 343{
 344        int off;
 345
 346        if (l4_mask->tos)
 347                return -EOPNOTSUPP;
 348
 349        if (l4_mask->ip4src) {
 350                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
 351                *(__be32 *)(key + off) = l4_value->ip4src;
 352                *(__be32 *)(mask + off) = l4_mask->ip4src;
 353        }
 354
 355        if (l4_mask->ip4dst) {
 356                off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
 357                *(__be32 *)(key + off) = l4_value->ip4dst;
 358                *(__be32 *)(mask + off) = l4_mask->ip4dst;
 359        }
 360
 361        if (l4_mask->psrc) {
 362                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
 363                *(__be16 *)(key + off) = l4_value->psrc;
 364                *(__be16 *)(mask + off) = l4_mask->psrc;
 365        }
 366
 367        if (l4_mask->pdst) {
 368                off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
 369                *(__be16 *)(key + off) = l4_value->pdst;
 370                *(__be16 *)(mask + off) = l4_mask->pdst;
 371        }
 372
 373        /* Only apply the rule for IPv4 frames with the specified L4 proto */
 374        off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
 375        *(__be16 *)(key + off) = htons(ETH_P_IP);
 376        *(__be16 *)(mask + off) = htons(0xFFFF);
 377
 378        off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
 379        *(u8 *)(key + off) = l4_proto;
 380        *(u8 *)(mask + off) = 0xFF;
 381
 382        return 0;
 383}
 384
 385static int prep_ext_rule(struct ethtool_flow_ext *ext_value,
 386                         struct ethtool_flow_ext *ext_mask,
 387                         void *key, void *mask)
 388{
 389        int off;
 390
 391        if (ext_mask->vlan_etype)
 392                return -EOPNOTSUPP;
 393
 394        if (ext_mask->vlan_tci) {
 395                off = dpaa2_eth_cls_fld_off(NET_PROT_VLAN, NH_FLD_VLAN_TCI);
 396                *(__be16 *)(key + off) = ext_value->vlan_tci;
 397                *(__be16 *)(mask + off) = ext_mask->vlan_tci;
 398        }
 399
 400        return 0;
 401}
 402
 403static int prep_mac_ext_rule(struct ethtool_flow_ext *ext_value,
 404                             struct ethtool_flow_ext *ext_mask,
 405                             void *key, void *mask)
 406{
 407        int off;
 408
 409        if (!is_zero_ether_addr(ext_mask->h_dest)) {
 410                off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
 411                ether_addr_copy(key + off, ext_value->h_dest);
 412                ether_addr_copy(mask + off, ext_mask->h_dest);
 413        }
 414
 415        return 0;
 416}
 417
 418static int prep_cls_rule(struct ethtool_rx_flow_spec *fs, void *key, void *mask)
 419{
 420        int err;
 421
 422        switch (fs->flow_type & 0xFF) {
 423        case ETHER_FLOW:
 424                err = prep_eth_rule(&fs->h_u.ether_spec, &fs->m_u.ether_spec,
 425                                    key, mask);
 426                break;
 427        case IP_USER_FLOW:
 428                err = prep_uip_rule(&fs->h_u.usr_ip4_spec,
 429                                    &fs->m_u.usr_ip4_spec, key, mask);
 430                break;
 431        case TCP_V4_FLOW:
 432                err = prep_l4_rule(&fs->h_u.tcp_ip4_spec, &fs->m_u.tcp_ip4_spec,
 433                                   key, mask, IPPROTO_TCP);
 434                break;
 435        case UDP_V4_FLOW:
 436                err = prep_l4_rule(&fs->h_u.udp_ip4_spec, &fs->m_u.udp_ip4_spec,
 437                                   key, mask, IPPROTO_UDP);
 438                break;
 439        case SCTP_V4_FLOW:
 440                err = prep_l4_rule(&fs->h_u.sctp_ip4_spec,
 441                                   &fs->m_u.sctp_ip4_spec, key, mask,
 442                                   IPPROTO_SCTP);
 443                break;
 444        default:
 445                return -EOPNOTSUPP;
 446        }
 447
 448        if (err)
 449                return err;
 450
 451        if (fs->flow_type & FLOW_EXT) {
 452                err = prep_ext_rule(&fs->h_ext, &fs->m_ext, key, mask);
 453                if (err)
 454                        return err;
 455        }
 456
 457        if (fs->flow_type & FLOW_MAC_EXT) {
 458                err = prep_mac_ext_rule(&fs->h_ext, &fs->m_ext, key, mask);
 459                if (err)
 460                        return err;
 461        }
 462
 463        return 0;
 464}
 465
 466static int do_cls_rule(struct net_device *net_dev,
 467                       struct ethtool_rx_flow_spec *fs,
 468                       bool add)
 469{
 470        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 471        struct device *dev = net_dev->dev.parent;
 472        struct dpni_rule_cfg rule_cfg = { 0 };
 473        struct dpni_fs_action_cfg fs_act = { 0 };
 474        dma_addr_t key_iova;
 475        void *key_buf;
 476        int err;
 477
 478        if (fs->ring_cookie != RX_CLS_FLOW_DISC &&
 479            fs->ring_cookie >= dpaa2_eth_queue_count(priv))
 480                return -EINVAL;
 481
 482        rule_cfg.key_size = dpaa2_eth_cls_key_size();
 483
 484        /* allocate twice the key size, for the actual key and for mask */
 485        key_buf = kzalloc(rule_cfg.key_size * 2, GFP_KERNEL);
 486        if (!key_buf)
 487                return -ENOMEM;
 488
 489        /* Fill the key and mask memory areas */
 490        err = prep_cls_rule(fs, key_buf, key_buf + rule_cfg.key_size);
 491        if (err)
 492                goto free_mem;
 493
 494        key_iova = dma_map_single(dev, key_buf, rule_cfg.key_size * 2,
 495                                  DMA_TO_DEVICE);
 496        if (dma_mapping_error(dev, key_iova)) {
 497                err = -ENOMEM;
 498                goto free_mem;
 499        }
 500
 501        rule_cfg.key_iova = key_iova;
 502        rule_cfg.mask_iova = key_iova + rule_cfg.key_size;
 503
 504        if (add) {
 505                if (fs->ring_cookie == RX_CLS_FLOW_DISC)
 506                        fs_act.options |= DPNI_FS_OPT_DISCARD;
 507                else
 508                        fs_act.flow_id = fs->ring_cookie;
 509                err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
 510                                        fs->location, &rule_cfg, &fs_act);
 511        } else {
 512                err = dpni_remove_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
 513                                           &rule_cfg);
 514        }
 515
 516        dma_unmap_single(dev, key_iova, rule_cfg.key_size * 2, DMA_TO_DEVICE);
 517
 518free_mem:
 519        kfree(key_buf);
 520
 521        return err;
 522}
 523
 524static int update_cls_rule(struct net_device *net_dev,
 525                           struct ethtool_rx_flow_spec *new_fs,
 526                           int location)
 527{
 528        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 529        struct dpaa2_eth_cls_rule *rule;
 530        int err = -EINVAL;
 531
 532        if (!priv->rx_cls_enabled)
 533                return -EOPNOTSUPP;
 534
 535        if (location >= dpaa2_eth_fs_count(priv))
 536                return -EINVAL;
 537
 538        rule = &priv->cls_rules[location];
 539
 540        /* If a rule is present at the specified location, delete it. */
 541        if (rule->in_use) {
 542                err = do_cls_rule(net_dev, &rule->fs, false);
 543                if (err)
 544                        return err;
 545
 546                rule->in_use = 0;
 547        }
 548
 549        /* If no new entry to add, return here */
 550        if (!new_fs)
 551                return err;
 552
 553        err = do_cls_rule(net_dev, new_fs, true);
 554        if (err)
 555                return err;
 556
 557        rule->in_use = 1;
 558        rule->fs = *new_fs;
 559
 560        return 0;
 561}
 562
 563static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
 564                               struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
 565{
 566        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 567        int max_rules = dpaa2_eth_fs_count(priv);
 568        int i, j = 0;
 569
 570        switch (rxnfc->cmd) {
 571        case ETHTOOL_GRXFH:
 572                /* we purposely ignore cmd->flow_type for now, because the
 573                 * classifier only supports a single set of fields for all
 574                 * protocols
 575                 */
 576                rxnfc->data = priv->rx_hash_fields;
 577                break;
 578        case ETHTOOL_GRXRINGS:
 579                rxnfc->data = dpaa2_eth_queue_count(priv);
 580                break;
 581        case ETHTOOL_GRXCLSRLCNT:
 582                rxnfc->rule_cnt = 0;
 583                for (i = 0; i < max_rules; i++)
 584                        if (priv->cls_rules[i].in_use)
 585                                rxnfc->rule_cnt++;
 586                rxnfc->data = max_rules;
 587                break;
 588        case ETHTOOL_GRXCLSRULE:
 589                if (rxnfc->fs.location >= max_rules)
 590                        return -EINVAL;
 591                if (!priv->cls_rules[rxnfc->fs.location].in_use)
 592                        return -EINVAL;
 593                rxnfc->fs = priv->cls_rules[rxnfc->fs.location].fs;
 594                break;
 595        case ETHTOOL_GRXCLSRLALL:
 596                for (i = 0; i < max_rules; i++) {
 597                        if (!priv->cls_rules[i].in_use)
 598                                continue;
 599                        if (j == rxnfc->rule_cnt)
 600                                return -EMSGSIZE;
 601                        rule_locs[j++] = i;
 602                }
 603                rxnfc->rule_cnt = j;
 604                rxnfc->data = max_rules;
 605                break;
 606        default:
 607                return -EOPNOTSUPP;
 608        }
 609
 610        return 0;
 611}
 612
 613static int dpaa2_eth_set_rxnfc(struct net_device *net_dev,
 614                               struct ethtool_rxnfc *rxnfc)
 615{
 616        int err = 0;
 617
 618        switch (rxnfc->cmd) {
 619        case ETHTOOL_SRXFH:
 620                if ((rxnfc->data & DPAA2_RXH_SUPPORTED) != rxnfc->data)
 621                        return -EOPNOTSUPP;
 622                err = dpaa2_eth_set_hash(net_dev, rxnfc->data);
 623                break;
 624        case ETHTOOL_SRXCLSRLINS:
 625                err = update_cls_rule(net_dev, &rxnfc->fs, rxnfc->fs.location);
 626                break;
 627        case ETHTOOL_SRXCLSRLDEL:
 628                err = update_cls_rule(net_dev, NULL, rxnfc->fs.location);
 629                break;
 630        default:
 631                err = -EOPNOTSUPP;
 632        }
 633
 634        return err;
 635}
 636
 637int dpaa2_phc_index = -1;
 638EXPORT_SYMBOL(dpaa2_phc_index);
 639
 640static int dpaa2_eth_get_ts_info(struct net_device *dev,
 641                                 struct ethtool_ts_info *info)
 642{
 643        info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
 644                                SOF_TIMESTAMPING_RX_HARDWARE |
 645                                SOF_TIMESTAMPING_RAW_HARDWARE;
 646
 647        info->phc_index = dpaa2_phc_index;
 648
 649        info->tx_types = (1 << HWTSTAMP_TX_OFF) |
 650                         (1 << HWTSTAMP_TX_ON);
 651
 652        info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
 653                           (1 << HWTSTAMP_FILTER_ALL);
 654        return 0;
 655}
 656
 657const struct ethtool_ops dpaa2_ethtool_ops = {
 658        .get_drvinfo = dpaa2_eth_get_drvinfo,
 659        .get_link = ethtool_op_get_link,
 660        .get_link_ksettings = dpaa2_eth_get_link_ksettings,
 661        .set_link_ksettings = dpaa2_eth_set_link_ksettings,
 662        .get_sset_count = dpaa2_eth_get_sset_count,
 663        .get_ethtool_stats = dpaa2_eth_get_ethtool_stats,
 664        .get_strings = dpaa2_eth_get_strings,
 665        .get_rxnfc = dpaa2_eth_get_rxnfc,
 666        .set_rxnfc = dpaa2_eth_set_rxnfc,
 667        .get_ts_info = dpaa2_eth_get_ts_info,
 668};
 669