This source file includes following definitions.
- dpaa_get_link_ksettings
- dpaa_set_link_ksettings
- dpaa_get_drvinfo
- dpaa_get_msglevel
- dpaa_set_msglevel
- dpaa_nway_reset
- dpaa_get_pauseparam
- dpaa_set_pauseparam
- dpaa_get_sset_count
- copy_stats
- dpaa_get_ethtool_stats
- dpaa_get_strings
- dpaa_get_hash_opts
- dpaa_get_rxnfc
- dpaa_set_hash
- dpaa_set_hash_opts
- dpaa_set_rxnfc
- dpaa_get_ts_info
- dpaa_get_coalesce
- dpaa_set_coalesce
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  33 
  34 #include <linux/string.h>
  35 #include <linux/of_platform.h>
  36 #include <linux/net_tstamp.h>
  37 #include <linux/fsl/ptp_qoriq.h>
  38 
  39 #include "dpaa_eth.h"
  40 #include "mac.h"
  41 
  42 static const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = {
  43         "interrupts",
  44         "rx packets",
  45         "tx packets",
  46         "tx confirm",
  47         "tx S/G",
  48         "tx error",
  49         "rx error",
  50 };
  51 
  52 static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
  53         
  54         "rx dma error",
  55         "rx frame physical error",
  56         "rx frame size error",
  57         "rx header error",
  58 
  59         
  60         "qman cg_tdrop",
  61         "qman wred",
  62         "qman error cond",
  63         "qman early window",
  64         "qman late window",
  65         "qman fq tdrop",
  66         "qman fq retired",
  67         "qman orp disabled",
  68 
  69         
  70         "congestion time (ms)",
  71         "entered congestion",
  72         "congested (0/1)"
  73 };
  74 
  75 #define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu)
  76 #define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global)
  77 
  78 static int dpaa_get_link_ksettings(struct net_device *net_dev,
  79                                    struct ethtool_link_ksettings *cmd)
  80 {
  81         if (!net_dev->phydev) {
  82                 netdev_dbg(net_dev, "phy device not initialized\n");
  83                 return 0;
  84         }
  85 
  86         phy_ethtool_ksettings_get(net_dev->phydev, cmd);
  87 
  88         return 0;
  89 }
  90 
  91 static int dpaa_set_link_ksettings(struct net_device *net_dev,
  92                                    const struct ethtool_link_ksettings *cmd)
  93 {
  94         int err;
  95 
  96         if (!net_dev->phydev) {
  97                 netdev_err(net_dev, "phy device not initialized\n");
  98                 return -ENODEV;
  99         }
 100 
 101         err = phy_ethtool_ksettings_set(net_dev->phydev, cmd);
 102         if (err < 0)
 103                 netdev_err(net_dev, "phy_ethtool_ksettings_set() = %d\n", err);
 104 
 105         return err;
 106 }
 107 
 108 static void dpaa_get_drvinfo(struct net_device *net_dev,
 109                              struct ethtool_drvinfo *drvinfo)
 110 {
 111         int len;
 112 
 113         strlcpy(drvinfo->driver, KBUILD_MODNAME,
 114                 sizeof(drvinfo->driver));
 115         len = snprintf(drvinfo->version, sizeof(drvinfo->version),
 116                        "%X", 0);
 117         len = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 118                        "%X", 0);
 119 
 120         if (len >= sizeof(drvinfo->fw_version)) {
 121                 
 122                 netdev_notice(net_dev, "snprintf() = %d\n", len);
 123         }
 124         strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
 125                 sizeof(drvinfo->bus_info));
 126 }
 127 
 128 static u32 dpaa_get_msglevel(struct net_device *net_dev)
 129 {
 130         return ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable;
 131 }
 132 
 133 static void dpaa_set_msglevel(struct net_device *net_dev,
 134                               u32 msg_enable)
 135 {
 136         ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable = msg_enable;
 137 }
 138 
 139 static int dpaa_nway_reset(struct net_device *net_dev)
 140 {
 141         int err;
 142 
 143         if (!net_dev->phydev) {
 144                 netdev_err(net_dev, "phy device not initialized\n");
 145                 return -ENODEV;
 146         }
 147 
 148         err = 0;
 149         if (net_dev->phydev->autoneg) {
 150                 err = phy_start_aneg(net_dev->phydev);
 151                 if (err < 0)
 152                         netdev_err(net_dev, "phy_start_aneg() = %d\n",
 153                                    err);
 154         }
 155 
 156         return err;
 157 }
 158 
 159 static void dpaa_get_pauseparam(struct net_device *net_dev,
 160                                 struct ethtool_pauseparam *epause)
 161 {
 162         struct mac_device *mac_dev;
 163         struct dpaa_priv *priv;
 164 
 165         priv = netdev_priv(net_dev);
 166         mac_dev = priv->mac_dev;
 167 
 168         if (!net_dev->phydev) {
 169                 netdev_err(net_dev, "phy device not initialized\n");
 170                 return;
 171         }
 172 
 173         epause->autoneg = mac_dev->autoneg_pause;
 174         epause->rx_pause = mac_dev->rx_pause_active;
 175         epause->tx_pause = mac_dev->tx_pause_active;
 176 }
 177 
 178 static int dpaa_set_pauseparam(struct net_device *net_dev,
 179                                struct ethtool_pauseparam *epause)
 180 {
 181         struct mac_device *mac_dev;
 182         struct phy_device *phydev;
 183         bool rx_pause, tx_pause;
 184         struct dpaa_priv *priv;
 185         int err;
 186 
 187         priv = netdev_priv(net_dev);
 188         mac_dev = priv->mac_dev;
 189 
 190         phydev = net_dev->phydev;
 191         if (!phydev) {
 192                 netdev_err(net_dev, "phy device not initialized\n");
 193                 return -ENODEV;
 194         }
 195 
 196         if (!phy_validate_pause(phydev, epause))
 197                 return -EINVAL;
 198 
 199         
 200 
 201 
 202 
 203         mac_dev->autoneg_pause = !!epause->autoneg;
 204         mac_dev->rx_pause_req = !!epause->rx_pause;
 205         mac_dev->tx_pause_req = !!epause->tx_pause;
 206 
 207         
 208 
 209 
 210 
 211         phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause);
 212 
 213         fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
 214         err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
 215         if (err < 0)
 216                 netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
 217 
 218         return err;
 219 }
 220 
 221 static int dpaa_get_sset_count(struct net_device *net_dev, int type)
 222 {
 223         unsigned int total_stats, num_stats;
 224 
 225         num_stats   = num_online_cpus() + 1;
 226         total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) +
 227                         DPAA_STATS_GLOBAL_LEN;
 228 
 229         switch (type) {
 230         case ETH_SS_STATS:
 231                 return total_stats;
 232         default:
 233                 return -EOPNOTSUPP;
 234         }
 235 }
 236 
 237 static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus,
 238                        int crr_cpu, u64 *bp_count, u64 *data)
 239 {
 240         int num_values = num_cpus + 1;
 241         int crr = 0, j;
 242 
 243         
 244         data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt;
 245         data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt;
 246 
 247         data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets;
 248         data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets;
 249 
 250         data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets;
 251         data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets;
 252 
 253         data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm;
 254         data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm;
 255 
 256         data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs;
 257         data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs;
 258 
 259         data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors;
 260         data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors;
 261 
 262         data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors;
 263         data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors;
 264 
 265         for (j = 0; j < DPAA_BPS_NUM; j++) {
 266                 data[crr * num_values + crr_cpu] = bp_count[j];
 267                 data[crr++ * num_values + num_cpus] += bp_count[j];
 268         }
 269 }
 270 
 271 static void dpaa_get_ethtool_stats(struct net_device *net_dev,
 272                                    struct ethtool_stats *stats, u64 *data)
 273 {
 274         u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num;
 275         struct dpaa_percpu_priv *percpu_priv;
 276         struct dpaa_rx_errors rx_errors;
 277         unsigned int num_cpus, offset;
 278         struct dpaa_ern_cnt ern_cnt;
 279         struct dpaa_bp *dpaa_bp;
 280         struct dpaa_priv *priv;
 281         int total_stats, i, j;
 282         bool cg_status;
 283 
 284         total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS);
 285         priv     = netdev_priv(net_dev);
 286         num_cpus = num_online_cpus();
 287 
 288         memset(&bp_count, 0, sizeof(bp_count));
 289         memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors));
 290         memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt));
 291         memset(data, 0, total_stats * sizeof(u64));
 292 
 293         for_each_online_cpu(i) {
 294                 percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
 295                 for (j = 0; j < DPAA_BPS_NUM; j++) {
 296                         dpaa_bp = priv->dpaa_bps[j];
 297                         if (!dpaa_bp->percpu_count)
 298                                 continue;
 299                         bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i));
 300                 }
 301                 rx_errors.dme += percpu_priv->rx_errors.dme;
 302                 rx_errors.fpe += percpu_priv->rx_errors.fpe;
 303                 rx_errors.fse += percpu_priv->rx_errors.fse;
 304                 rx_errors.phe += percpu_priv->rx_errors.phe;
 305 
 306                 ern_cnt.cg_tdrop     += percpu_priv->ern_cnt.cg_tdrop;
 307                 ern_cnt.wred         += percpu_priv->ern_cnt.wred;
 308                 ern_cnt.err_cond     += percpu_priv->ern_cnt.err_cond;
 309                 ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
 310                 ern_cnt.late_window  += percpu_priv->ern_cnt.late_window;
 311                 ern_cnt.fq_tdrop     += percpu_priv->ern_cnt.fq_tdrop;
 312                 ern_cnt.fq_retired   += percpu_priv->ern_cnt.fq_retired;
 313                 ern_cnt.orp_zero     += percpu_priv->ern_cnt.orp_zero;
 314 
 315                 copy_stats(percpu_priv, num_cpus, i, bp_count, data);
 316         }
 317 
 318         offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM);
 319         memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors));
 320 
 321         offset += sizeof(struct dpaa_rx_errors) / sizeof(u64);
 322         memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt));
 323 
 324         
 325         cg_num    = 0;
 326         cg_status = false;
 327         cg_time   = jiffies_to_msecs(priv->cgr_data.congested_jiffies);
 328         if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) {
 329                 cg_num    = priv->cgr_data.cgr_congested_count;
 330 
 331                 
 332                 priv->cgr_data.congested_jiffies   = 0;
 333                 priv->cgr_data.cgr_congested_count = 0;
 334         }
 335 
 336         offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64);
 337         data[offset++] = cg_time;
 338         data[offset++] = cg_num;
 339         data[offset++] = cg_status;
 340 }
 341 
 342 static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
 343                              u8 *data)
 344 {
 345         unsigned int i, j, num_cpus, size;
 346         char string_cpu[ETH_GSTRING_LEN];
 347         u8 *strings;
 348 
 349         memset(string_cpu, 0, sizeof(string_cpu));
 350         strings   = data;
 351         num_cpus  = num_online_cpus();
 352         size      = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN;
 353 
 354         for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) {
 355                 for (j = 0; j < num_cpus; j++) {
 356                         snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]",
 357                                  dpaa_stats_percpu[i], j);
 358                         memcpy(strings, string_cpu, ETH_GSTRING_LEN);
 359                         strings += ETH_GSTRING_LEN;
 360                 }
 361                 snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]",
 362                          dpaa_stats_percpu[i]);
 363                 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
 364                 strings += ETH_GSTRING_LEN;
 365         }
 366         for (i = 0; i < DPAA_BPS_NUM; i++) {
 367                 for (j = 0; j < num_cpus; j++) {
 368                         snprintf(string_cpu, ETH_GSTRING_LEN,
 369                                  "bpool %c [CPU %d]", 'a' + i, j);
 370                         memcpy(strings, string_cpu, ETH_GSTRING_LEN);
 371                         strings += ETH_GSTRING_LEN;
 372                 }
 373                 snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]",
 374                          'a' + i);
 375                 memcpy(strings, string_cpu, ETH_GSTRING_LEN);
 376                 strings += ETH_GSTRING_LEN;
 377         }
 378         memcpy(strings, dpaa_stats_global, size);
 379 }
 380 
 381 static int dpaa_get_hash_opts(struct net_device *dev,
 382                               struct ethtool_rxnfc *cmd)
 383 {
 384         struct dpaa_priv *priv = netdev_priv(dev);
 385 
 386         cmd->data = 0;
 387 
 388         switch (cmd->flow_type) {
 389         case TCP_V4_FLOW:
 390         case TCP_V6_FLOW:
 391         case UDP_V4_FLOW:
 392         case UDP_V6_FLOW:
 393                 if (priv->keygen_in_use)
 394                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 395                 
 396         case IPV4_FLOW:
 397         case IPV6_FLOW:
 398         case SCTP_V4_FLOW:
 399         case SCTP_V6_FLOW:
 400         case AH_ESP_V4_FLOW:
 401         case AH_ESP_V6_FLOW:
 402         case AH_V4_FLOW:
 403         case AH_V6_FLOW:
 404         case ESP_V4_FLOW:
 405         case ESP_V6_FLOW:
 406                 if (priv->keygen_in_use)
 407                         cmd->data |= RXH_IP_SRC | RXH_IP_DST;
 408                 break;
 409         default:
 410                 cmd->data = 0;
 411                 break;
 412         }
 413 
 414         return 0;
 415 }
 416 
 417 static int dpaa_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 418                           u32 *unused)
 419 {
 420         int ret = -EOPNOTSUPP;
 421 
 422         switch (cmd->cmd) {
 423         case ETHTOOL_GRXFH:
 424                 ret = dpaa_get_hash_opts(dev, cmd);
 425                 break;
 426         default:
 427                 break;
 428         }
 429 
 430         return ret;
 431 }
 432 
 433 static void dpaa_set_hash(struct net_device *net_dev, bool enable)
 434 {
 435         struct mac_device *mac_dev;
 436         struct fman_port *rxport;
 437         struct dpaa_priv *priv;
 438 
 439         priv = netdev_priv(net_dev);
 440         mac_dev = priv->mac_dev;
 441         rxport = mac_dev->port[0];
 442 
 443         fman_port_use_kg_hash(rxport, enable);
 444         priv->keygen_in_use = enable;
 445 }
 446 
 447 static int dpaa_set_hash_opts(struct net_device *dev,
 448                               struct ethtool_rxnfc *nfc)
 449 {
 450         int ret = -EINVAL;
 451 
 452         
 453         if (nfc->data &
 454             ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
 455                 return -EINVAL;
 456 
 457         switch (nfc->flow_type) {
 458         case TCP_V4_FLOW:
 459         case TCP_V6_FLOW:
 460         case UDP_V4_FLOW:
 461         case UDP_V6_FLOW:
 462         case IPV4_FLOW:
 463         case IPV6_FLOW:
 464         case SCTP_V4_FLOW:
 465         case SCTP_V6_FLOW:
 466         case AH_ESP_V4_FLOW:
 467         case AH_ESP_V6_FLOW:
 468         case AH_V4_FLOW:
 469         case AH_V6_FLOW:
 470         case ESP_V4_FLOW:
 471         case ESP_V6_FLOW:
 472                 dpaa_set_hash(dev, !!nfc->data);
 473                 ret = 0;
 474                 break;
 475         default:
 476                 break;
 477         }
 478 
 479         return ret;
 480 }
 481 
 482 static int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 483 {
 484         int ret = -EOPNOTSUPP;
 485 
 486         switch (cmd->cmd) {
 487         case ETHTOOL_SRXFH:
 488                 ret = dpaa_set_hash_opts(dev, cmd);
 489                 break;
 490         default:
 491                 break;
 492         }
 493 
 494         return ret;
 495 }
 496 
 497 static int dpaa_get_ts_info(struct net_device *net_dev,
 498                             struct ethtool_ts_info *info)
 499 {
 500         struct device *dev = net_dev->dev.parent;
 501         struct device_node *mac_node = dev->of_node;
 502         struct device_node *fman_node = NULL, *ptp_node = NULL;
 503         struct platform_device *ptp_dev = NULL;
 504         struct ptp_qoriq *ptp = NULL;
 505 
 506         info->phc_index = -1;
 507 
 508         fman_node = of_get_parent(mac_node);
 509         if (fman_node)
 510                 ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
 511 
 512         if (ptp_node)
 513                 ptp_dev = of_find_device_by_node(ptp_node);
 514 
 515         if (ptp_dev)
 516                 ptp = platform_get_drvdata(ptp_dev);
 517 
 518         if (ptp)
 519                 info->phc_index = ptp->phc_index;
 520 
 521         info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
 522                                 SOF_TIMESTAMPING_RX_HARDWARE |
 523                                 SOF_TIMESTAMPING_RAW_HARDWARE;
 524         info->tx_types = (1 << HWTSTAMP_TX_OFF) |
 525                          (1 << HWTSTAMP_TX_ON);
 526         info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
 527                            (1 << HWTSTAMP_FILTER_ALL);
 528 
 529         return 0;
 530 }
 531 
 532 static int dpaa_get_coalesce(struct net_device *dev,
 533                              struct ethtool_coalesce *c)
 534 {
 535         struct qman_portal *portal;
 536         u32 period;
 537         u8 thresh;
 538 
 539         portal = qman_get_affine_portal(smp_processor_id());
 540         qman_portal_get_iperiod(portal, &period);
 541         qman_dqrr_get_ithresh(portal, &thresh);
 542 
 543         c->rx_coalesce_usecs = period;
 544         c->rx_max_coalesced_frames = thresh;
 545         c->use_adaptive_rx_coalesce = false;
 546 
 547         return 0;
 548 }
 549 
 550 static int dpaa_set_coalesce(struct net_device *dev,
 551                              struct ethtool_coalesce *c)
 552 {
 553         const cpumask_t *cpus = qman_affine_cpus();
 554         bool needs_revert[NR_CPUS] = {false};
 555         struct qman_portal *portal;
 556         u32 period, prev_period;
 557         u8 thresh, prev_thresh;
 558         int cpu, res;
 559 
 560         if (c->use_adaptive_rx_coalesce)
 561                 return -EINVAL;
 562 
 563         period = c->rx_coalesce_usecs;
 564         thresh = c->rx_max_coalesced_frames;
 565 
 566         
 567         portal = qman_get_affine_portal(smp_processor_id());
 568         qman_portal_get_iperiod(portal, &prev_period);
 569         qman_dqrr_get_ithresh(portal, &prev_thresh);
 570 
 571         
 572         for_each_cpu_and(cpu, cpus, cpu_online_mask) {
 573                 portal = qman_get_affine_portal(cpu);
 574                 res = qman_portal_set_iperiod(portal, period);
 575                 if (res)
 576                         goto revert_values;
 577                 res = qman_dqrr_set_ithresh(portal, thresh);
 578                 if (res) {
 579                         qman_portal_set_iperiod(portal, prev_period);
 580                         goto revert_values;
 581                 }
 582                 needs_revert[cpu] = true;
 583         }
 584 
 585         return 0;
 586 
 587 revert_values:
 588         
 589         for_each_cpu_and(cpu, cpus, cpu_online_mask) {
 590                 if (!needs_revert[cpu])
 591                         continue;
 592                 portal = qman_get_affine_portal(cpu);
 593                 
 594                 qman_portal_set_iperiod(portal, prev_period);
 595                 qman_dqrr_set_ithresh(portal, prev_thresh);
 596         }
 597 
 598         return res;
 599 }
 600 
 601 const struct ethtool_ops dpaa_ethtool_ops = {
 602         .get_drvinfo = dpaa_get_drvinfo,
 603         .get_msglevel = dpaa_get_msglevel,
 604         .set_msglevel = dpaa_set_msglevel,
 605         .nway_reset = dpaa_nway_reset,
 606         .get_pauseparam = dpaa_get_pauseparam,
 607         .set_pauseparam = dpaa_set_pauseparam,
 608         .get_link = ethtool_op_get_link,
 609         .get_sset_count = dpaa_get_sset_count,
 610         .get_ethtool_stats = dpaa_get_ethtool_stats,
 611         .get_strings = dpaa_get_strings,
 612         .get_link_ksettings = dpaa_get_link_ksettings,
 613         .set_link_ksettings = dpaa_set_link_ksettings,
 614         .get_rxnfc = dpaa_get_rxnfc,
 615         .set_rxnfc = dpaa_set_rxnfc,
 616         .get_ts_info = dpaa_get_ts_info,
 617         .get_coalesce = dpaa_get_coalesce,
 618         .set_coalesce = dpaa_set_coalesce,
 619 };