| .. | .. |
|---|
| 47 | 47 | "tx S/G", |
|---|
| 48 | 48 | "tx error", |
|---|
| 49 | 49 | "rx error", |
|---|
| 50 | + "rx dropped", |
|---|
| 51 | + "tx dropped", |
|---|
| 50 | 52 | }; |
|---|
| 51 | 53 | |
|---|
| 52 | 54 | static char dpaa_stats_global[][ETH_GSTRING_LEN] = { |
|---|
| .. | .. |
|---|
| 78 | 80 | static int dpaa_get_link_ksettings(struct net_device *net_dev, |
|---|
| 79 | 81 | struct ethtool_link_ksettings *cmd) |
|---|
| 80 | 82 | { |
|---|
| 81 | | - if (!net_dev->phydev) { |
|---|
| 82 | | - netdev_dbg(net_dev, "phy device not initialized\n"); |
|---|
| 83 | + if (!net_dev->phydev) |
|---|
| 83 | 84 | return 0; |
|---|
| 84 | | - } |
|---|
| 85 | 85 | |
|---|
| 86 | 86 | phy_ethtool_ksettings_get(net_dev->phydev, cmd); |
|---|
| 87 | 87 | |
|---|
| .. | .. |
|---|
| 93 | 93 | { |
|---|
| 94 | 94 | int err; |
|---|
| 95 | 95 | |
|---|
| 96 | | - if (!net_dev->phydev) { |
|---|
| 97 | | - netdev_err(net_dev, "phy device not initialized\n"); |
|---|
| 96 | + if (!net_dev->phydev) |
|---|
| 98 | 97 | return -ENODEV; |
|---|
| 99 | | - } |
|---|
| 100 | 98 | |
|---|
| 101 | 99 | err = phy_ethtool_ksettings_set(net_dev->phydev, cmd); |
|---|
| 102 | 100 | if (err < 0) |
|---|
| .. | .. |
|---|
| 108 | 106 | static void dpaa_get_drvinfo(struct net_device *net_dev, |
|---|
| 109 | 107 | struct ethtool_drvinfo *drvinfo) |
|---|
| 110 | 108 | { |
|---|
| 111 | | - int len; |
|---|
| 112 | | - |
|---|
| 113 | 109 | strlcpy(drvinfo->driver, KBUILD_MODNAME, |
|---|
| 114 | 110 | 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 | | - /* Truncated output */ |
|---|
| 122 | | - netdev_notice(net_dev, "snprintf() = %d\n", len); |
|---|
| 123 | | - } |
|---|
| 124 | 111 | strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), |
|---|
| 125 | 112 | sizeof(drvinfo->bus_info)); |
|---|
| 126 | 113 | } |
|---|
| .. | .. |
|---|
| 140 | 127 | { |
|---|
| 141 | 128 | int err; |
|---|
| 142 | 129 | |
|---|
| 143 | | - if (!net_dev->phydev) { |
|---|
| 144 | | - netdev_err(net_dev, "phy device not initialized\n"); |
|---|
| 130 | + if (!net_dev->phydev) |
|---|
| 145 | 131 | return -ENODEV; |
|---|
| 146 | | - } |
|---|
| 147 | 132 | |
|---|
| 148 | 133 | err = 0; |
|---|
| 149 | 134 | if (net_dev->phydev->autoneg) { |
|---|
| .. | .. |
|---|
| 165 | 150 | priv = netdev_priv(net_dev); |
|---|
| 166 | 151 | mac_dev = priv->mac_dev; |
|---|
| 167 | 152 | |
|---|
| 168 | | - if (!net_dev->phydev) { |
|---|
| 169 | | - netdev_err(net_dev, "phy device not initialized\n"); |
|---|
| 153 | + if (!net_dev->phydev) |
|---|
| 170 | 154 | return; |
|---|
| 171 | | - } |
|---|
| 172 | 155 | |
|---|
| 173 | 156 | epause->autoneg = mac_dev->autoneg_pause; |
|---|
| 174 | 157 | epause->rx_pause = mac_dev->rx_pause_active; |
|---|
| .. | .. |
|---|
| 182 | 165 | struct phy_device *phydev; |
|---|
| 183 | 166 | bool rx_pause, tx_pause; |
|---|
| 184 | 167 | struct dpaa_priv *priv; |
|---|
| 185 | | - u32 newadv, oldadv; |
|---|
| 186 | 168 | int err; |
|---|
| 187 | 169 | |
|---|
| 188 | 170 | priv = netdev_priv(net_dev); |
|---|
| .. | .. |
|---|
| 194 | 176 | return -ENODEV; |
|---|
| 195 | 177 | } |
|---|
| 196 | 178 | |
|---|
| 197 | | - if (!(phydev->supported & SUPPORTED_Pause) || |
|---|
| 198 | | - (!(phydev->supported & SUPPORTED_Asym_Pause) && |
|---|
| 199 | | - (epause->rx_pause != epause->tx_pause))) |
|---|
| 179 | + if (!phy_validate_pause(phydev, epause)) |
|---|
| 200 | 180 | return -EINVAL; |
|---|
| 201 | 181 | |
|---|
| 202 | 182 | /* The MAC should know how to handle PAUSE frame autonegotiation before |
|---|
| .. | .. |
|---|
| 210 | 190 | /* Determine the sym/asym advertised PAUSE capabilities from the desired |
|---|
| 211 | 191 | * rx/tx pause settings. |
|---|
| 212 | 192 | */ |
|---|
| 213 | | - newadv = 0; |
|---|
| 214 | | - if (epause->rx_pause) |
|---|
| 215 | | - newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause; |
|---|
| 216 | | - if (epause->tx_pause) |
|---|
| 217 | | - newadv ^= ADVERTISED_Asym_Pause; |
|---|
| 218 | 193 | |
|---|
| 219 | | - oldadv = phydev->advertising & |
|---|
| 220 | | - (ADVERTISED_Pause | ADVERTISED_Asym_Pause); |
|---|
| 221 | | - |
|---|
| 222 | | - /* If there are differences between the old and the new advertised |
|---|
| 223 | | - * values, restart PHY autonegotiation and advertise the new values. |
|---|
| 224 | | - */ |
|---|
| 225 | | - if (oldadv != newadv) { |
|---|
| 226 | | - phydev->advertising &= ~(ADVERTISED_Pause |
|---|
| 227 | | - | ADVERTISED_Asym_Pause); |
|---|
| 228 | | - phydev->advertising |= newadv; |
|---|
| 229 | | - if (phydev->autoneg) { |
|---|
| 230 | | - err = phy_start_aneg(phydev); |
|---|
| 231 | | - if (err < 0) |
|---|
| 232 | | - netdev_err(net_dev, "phy_start_aneg() = %d\n", |
|---|
| 233 | | - err); |
|---|
| 234 | | - } |
|---|
| 235 | | - } |
|---|
| 194 | + phy_set_asym_pause(phydev, epause->rx_pause, epause->tx_pause); |
|---|
| 236 | 195 | |
|---|
| 237 | 196 | fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); |
|---|
| 238 | 197 | err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); |
|---|
| .. | .. |
|---|
| 247 | 206 | unsigned int total_stats, num_stats; |
|---|
| 248 | 207 | |
|---|
| 249 | 208 | num_stats = num_online_cpus() + 1; |
|---|
| 250 | | - total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) + |
|---|
| 209 | + total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + 1) + |
|---|
| 251 | 210 | DPAA_STATS_GLOBAL_LEN; |
|---|
| 252 | 211 | |
|---|
| 253 | 212 | switch (type) { |
|---|
| .. | .. |
|---|
| 259 | 218 | } |
|---|
| 260 | 219 | |
|---|
| 261 | 220 | static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus, |
|---|
| 262 | | - int crr_cpu, u64 *bp_count, u64 *data) |
|---|
| 221 | + int crr_cpu, u64 bp_count, u64 *data) |
|---|
| 263 | 222 | { |
|---|
| 264 | 223 | int num_values = num_cpus + 1; |
|---|
| 265 | | - int crr = 0, j; |
|---|
| 224 | + int crr = 0; |
|---|
| 266 | 225 | |
|---|
| 267 | 226 | /* update current CPU's stats and also add them to the total values */ |
|---|
| 268 | 227 | data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt; |
|---|
| .. | .. |
|---|
| 286 | 245 | data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors; |
|---|
| 287 | 246 | data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors; |
|---|
| 288 | 247 | |
|---|
| 289 | | - for (j = 0; j < DPAA_BPS_NUM; j++) { |
|---|
| 290 | | - data[crr * num_values + crr_cpu] = bp_count[j]; |
|---|
| 291 | | - data[crr++ * num_values + num_cpus] += bp_count[j]; |
|---|
| 292 | | - } |
|---|
| 248 | + data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_dropped; |
|---|
| 249 | + data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_dropped; |
|---|
| 250 | + |
|---|
| 251 | + data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_dropped; |
|---|
| 252 | + data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_dropped; |
|---|
| 253 | + |
|---|
| 254 | + data[crr * num_values + crr_cpu] = bp_count; |
|---|
| 255 | + data[crr++ * num_values + num_cpus] += bp_count; |
|---|
| 293 | 256 | } |
|---|
| 294 | 257 | |
|---|
| 295 | 258 | static void dpaa_get_ethtool_stats(struct net_device *net_dev, |
|---|
| 296 | 259 | struct ethtool_stats *stats, u64 *data) |
|---|
| 297 | 260 | { |
|---|
| 298 | | - u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num; |
|---|
| 299 | 261 | struct dpaa_percpu_priv *percpu_priv; |
|---|
| 300 | 262 | struct dpaa_rx_errors rx_errors; |
|---|
| 301 | 263 | unsigned int num_cpus, offset; |
|---|
| 264 | + u64 bp_count, cg_time, cg_num; |
|---|
| 302 | 265 | struct dpaa_ern_cnt ern_cnt; |
|---|
| 303 | 266 | struct dpaa_bp *dpaa_bp; |
|---|
| 304 | 267 | struct dpaa_priv *priv; |
|---|
| 305 | | - int total_stats, i, j; |
|---|
| 268 | + int total_stats, i; |
|---|
| 306 | 269 | bool cg_status; |
|---|
| 307 | 270 | |
|---|
| 308 | 271 | total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS); |
|---|
| .. | .. |
|---|
| 316 | 279 | |
|---|
| 317 | 280 | for_each_online_cpu(i) { |
|---|
| 318 | 281 | percpu_priv = per_cpu_ptr(priv->percpu_priv, i); |
|---|
| 319 | | - for (j = 0; j < DPAA_BPS_NUM; j++) { |
|---|
| 320 | | - dpaa_bp = priv->dpaa_bps[j]; |
|---|
| 321 | | - if (!dpaa_bp->percpu_count) |
|---|
| 322 | | - continue; |
|---|
| 323 | | - bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i)); |
|---|
| 324 | | - } |
|---|
| 282 | + dpaa_bp = priv->dpaa_bp; |
|---|
| 283 | + if (!dpaa_bp->percpu_count) |
|---|
| 284 | + continue; |
|---|
| 285 | + bp_count = *(per_cpu_ptr(dpaa_bp->percpu_count, i)); |
|---|
| 325 | 286 | rx_errors.dme += percpu_priv->rx_errors.dme; |
|---|
| 326 | 287 | rx_errors.fpe += percpu_priv->rx_errors.fpe; |
|---|
| 327 | 288 | rx_errors.fse += percpu_priv->rx_errors.fse; |
|---|
| .. | .. |
|---|
| 339 | 300 | copy_stats(percpu_priv, num_cpus, i, bp_count, data); |
|---|
| 340 | 301 | } |
|---|
| 341 | 302 | |
|---|
| 342 | | - offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM); |
|---|
| 303 | + offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + 1); |
|---|
| 343 | 304 | memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors)); |
|---|
| 344 | 305 | |
|---|
| 345 | 306 | offset += sizeof(struct dpaa_rx_errors) / sizeof(u64); |
|---|
| .. | .. |
|---|
| 387 | 348 | memcpy(strings, string_cpu, ETH_GSTRING_LEN); |
|---|
| 388 | 349 | strings += ETH_GSTRING_LEN; |
|---|
| 389 | 350 | } |
|---|
| 390 | | - for (i = 0; i < DPAA_BPS_NUM; i++) { |
|---|
| 391 | | - for (j = 0; j < num_cpus; j++) { |
|---|
| 392 | | - snprintf(string_cpu, ETH_GSTRING_LEN, |
|---|
| 393 | | - "bpool %c [CPU %d]", 'a' + i, j); |
|---|
| 394 | | - memcpy(strings, string_cpu, ETH_GSTRING_LEN); |
|---|
| 395 | | - strings += ETH_GSTRING_LEN; |
|---|
| 396 | | - } |
|---|
| 397 | | - snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]", |
|---|
| 398 | | - 'a' + i); |
|---|
| 351 | + for (j = 0; j < num_cpus; j++) { |
|---|
| 352 | + snprintf(string_cpu, ETH_GSTRING_LEN, |
|---|
| 353 | + "bpool [CPU %d]", j); |
|---|
| 399 | 354 | memcpy(strings, string_cpu, ETH_GSTRING_LEN); |
|---|
| 400 | 355 | strings += ETH_GSTRING_LEN; |
|---|
| 401 | 356 | } |
|---|
| 357 | + snprintf(string_cpu, ETH_GSTRING_LEN, "bpool [TOTAL]"); |
|---|
| 358 | + memcpy(strings, string_cpu, ETH_GSTRING_LEN); |
|---|
| 359 | + strings += ETH_GSTRING_LEN; |
|---|
| 360 | + |
|---|
| 402 | 361 | memcpy(strings, dpaa_stats_global, size); |
|---|
| 403 | 362 | } |
|---|
| 404 | 363 | |
|---|
| .. | .. |
|---|
| 416 | 375 | case UDP_V6_FLOW: |
|---|
| 417 | 376 | if (priv->keygen_in_use) |
|---|
| 418 | 377 | cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; |
|---|
| 419 | | - /* Fall through */ |
|---|
| 378 | + fallthrough; |
|---|
| 420 | 379 | case IPV4_FLOW: |
|---|
| 421 | 380 | case IPV6_FLOW: |
|---|
| 422 | 381 | case SCTP_V4_FLOW: |
|---|
| .. | .. |
|---|
| 525 | 484 | struct device_node *mac_node = dev->of_node; |
|---|
| 526 | 485 | struct device_node *fman_node = NULL, *ptp_node = NULL; |
|---|
| 527 | 486 | struct platform_device *ptp_dev = NULL; |
|---|
| 528 | | - struct qoriq_ptp *ptp = NULL; |
|---|
| 487 | + struct ptp_qoriq *ptp = NULL; |
|---|
| 529 | 488 | |
|---|
| 530 | 489 | info->phc_index = -1; |
|---|
| 531 | 490 | |
|---|
| 532 | 491 | fman_node = of_get_parent(mac_node); |
|---|
| 533 | | - if (fman_node) |
|---|
| 492 | + if (fman_node) { |
|---|
| 534 | 493 | ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0); |
|---|
| 494 | + of_node_put(fman_node); |
|---|
| 495 | + } |
|---|
| 535 | 496 | |
|---|
| 536 | | - if (ptp_node) |
|---|
| 497 | + if (ptp_node) { |
|---|
| 537 | 498 | ptp_dev = of_find_device_by_node(ptp_node); |
|---|
| 499 | + of_node_put(ptp_node); |
|---|
| 500 | + } |
|---|
| 538 | 501 | |
|---|
| 539 | 502 | if (ptp_dev) |
|---|
| 540 | 503 | ptp = platform_get_drvdata(ptp_dev); |
|---|
| .. | .. |
|---|
| 553 | 516 | return 0; |
|---|
| 554 | 517 | } |
|---|
| 555 | 518 | |
|---|
| 519 | +static int dpaa_get_coalesce(struct net_device *dev, |
|---|
| 520 | + struct ethtool_coalesce *c) |
|---|
| 521 | +{ |
|---|
| 522 | + struct qman_portal *portal; |
|---|
| 523 | + u32 period; |
|---|
| 524 | + u8 thresh; |
|---|
| 525 | + |
|---|
| 526 | + portal = qman_get_affine_portal(smp_processor_id()); |
|---|
| 527 | + qman_portal_get_iperiod(portal, &period); |
|---|
| 528 | + qman_dqrr_get_ithresh(portal, &thresh); |
|---|
| 529 | + |
|---|
| 530 | + c->rx_coalesce_usecs = period; |
|---|
| 531 | + c->rx_max_coalesced_frames = thresh; |
|---|
| 532 | + |
|---|
| 533 | + return 0; |
|---|
| 534 | +} |
|---|
| 535 | + |
|---|
| 536 | +static int dpaa_set_coalesce(struct net_device *dev, |
|---|
| 537 | + struct ethtool_coalesce *c) |
|---|
| 538 | +{ |
|---|
| 539 | + const cpumask_t *cpus = qman_affine_cpus(); |
|---|
| 540 | + bool needs_revert[NR_CPUS] = {false}; |
|---|
| 541 | + struct qman_portal *portal; |
|---|
| 542 | + u32 period, prev_period; |
|---|
| 543 | + u8 thresh, prev_thresh; |
|---|
| 544 | + int cpu, res; |
|---|
| 545 | + |
|---|
| 546 | + period = c->rx_coalesce_usecs; |
|---|
| 547 | + thresh = c->rx_max_coalesced_frames; |
|---|
| 548 | + |
|---|
| 549 | + /* save previous values */ |
|---|
| 550 | + portal = qman_get_affine_portal(smp_processor_id()); |
|---|
| 551 | + qman_portal_get_iperiod(portal, &prev_period); |
|---|
| 552 | + qman_dqrr_get_ithresh(portal, &prev_thresh); |
|---|
| 553 | + |
|---|
| 554 | + /* set new values */ |
|---|
| 555 | + for_each_cpu_and(cpu, cpus, cpu_online_mask) { |
|---|
| 556 | + portal = qman_get_affine_portal(cpu); |
|---|
| 557 | + res = qman_portal_set_iperiod(portal, period); |
|---|
| 558 | + if (res) |
|---|
| 559 | + goto revert_values; |
|---|
| 560 | + res = qman_dqrr_set_ithresh(portal, thresh); |
|---|
| 561 | + if (res) { |
|---|
| 562 | + qman_portal_set_iperiod(portal, prev_period); |
|---|
| 563 | + goto revert_values; |
|---|
| 564 | + } |
|---|
| 565 | + needs_revert[cpu] = true; |
|---|
| 566 | + } |
|---|
| 567 | + |
|---|
| 568 | + return 0; |
|---|
| 569 | + |
|---|
| 570 | +revert_values: |
|---|
| 571 | + /* restore previous values */ |
|---|
| 572 | + for_each_cpu_and(cpu, cpus, cpu_online_mask) { |
|---|
| 573 | + if (!needs_revert[cpu]) |
|---|
| 574 | + continue; |
|---|
| 575 | + portal = qman_get_affine_portal(cpu); |
|---|
| 576 | + /* previous values will not fail, ignore return value */ |
|---|
| 577 | + qman_portal_set_iperiod(portal, prev_period); |
|---|
| 578 | + qman_dqrr_set_ithresh(portal, prev_thresh); |
|---|
| 579 | + } |
|---|
| 580 | + |
|---|
| 581 | + return res; |
|---|
| 582 | +} |
|---|
| 583 | + |
|---|
| 556 | 584 | const struct ethtool_ops dpaa_ethtool_ops = { |
|---|
| 585 | + .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | |
|---|
| 586 | + ETHTOOL_COALESCE_RX_MAX_FRAMES, |
|---|
| 557 | 587 | .get_drvinfo = dpaa_get_drvinfo, |
|---|
| 558 | 588 | .get_msglevel = dpaa_get_msglevel, |
|---|
| 559 | 589 | .set_msglevel = dpaa_set_msglevel, |
|---|
| .. | .. |
|---|
| 569 | 599 | .get_rxnfc = dpaa_get_rxnfc, |
|---|
| 570 | 600 | .set_rxnfc = dpaa_set_rxnfc, |
|---|
| 571 | 601 | .get_ts_info = dpaa_get_ts_info, |
|---|
| 602 | + .get_coalesce = dpaa_get_coalesce, |
|---|
| 603 | + .set_coalesce = dpaa_set_coalesce, |
|---|
| 572 | 604 | }; |
|---|