162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2008 - 2016 Freescale Semiconductor Inc. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/string.h> 962306a36Sopenharmony_ci#include <linux/of.h> 1062306a36Sopenharmony_ci#include <linux/of_platform.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/net_tstamp.h> 1362306a36Sopenharmony_ci#include <linux/fsl/ptp_qoriq.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "dpaa_eth.h" 1662306a36Sopenharmony_ci#include "mac.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = { 1962306a36Sopenharmony_ci "interrupts", 2062306a36Sopenharmony_ci "rx packets", 2162306a36Sopenharmony_ci "tx packets", 2262306a36Sopenharmony_ci "tx confirm", 2362306a36Sopenharmony_ci "tx S/G", 2462306a36Sopenharmony_ci "tx error", 2562306a36Sopenharmony_ci "rx error", 2662306a36Sopenharmony_ci "rx dropped", 2762306a36Sopenharmony_ci "tx dropped", 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic char dpaa_stats_global[][ETH_GSTRING_LEN] = { 3162306a36Sopenharmony_ci /* dpa rx errors */ 3262306a36Sopenharmony_ci "rx dma error", 3362306a36Sopenharmony_ci "rx frame physical error", 3462306a36Sopenharmony_ci "rx frame size error", 3562306a36Sopenharmony_ci "rx header error", 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci /* demultiplexing errors */ 3862306a36Sopenharmony_ci "qman cg_tdrop", 3962306a36Sopenharmony_ci "qman wred", 4062306a36Sopenharmony_ci "qman error cond", 4162306a36Sopenharmony_ci "qman early window", 4262306a36Sopenharmony_ci "qman late window", 4362306a36Sopenharmony_ci "qman fq tdrop", 4462306a36Sopenharmony_ci "qman fq retired", 4562306a36Sopenharmony_ci "qman orp disabled", 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* congestion related stats */ 4862306a36Sopenharmony_ci "congestion time (ms)", 4962306a36Sopenharmony_ci "entered congestion", 5062306a36Sopenharmony_ci "congested (0/1)" 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu) 5462306a36Sopenharmony_ci#define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int dpaa_get_link_ksettings(struct net_device *net_dev, 5762306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(net_dev); 6062306a36Sopenharmony_ci struct mac_device *mac_dev = priv->mac_dev; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return phylink_ethtool_ksettings_get(mac_dev->phylink, cmd); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int dpaa_set_link_ksettings(struct net_device *net_dev, 6662306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(net_dev); 6962306a36Sopenharmony_ci struct mac_device *mac_dev = priv->mac_dev; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return phylink_ethtool_ksettings_set(mac_dev->phylink, cmd); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void dpaa_get_drvinfo(struct net_device *net_dev, 7562306a36Sopenharmony_ci struct ethtool_drvinfo *drvinfo) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci strscpy(drvinfo->driver, KBUILD_MODNAME, 7862306a36Sopenharmony_ci sizeof(drvinfo->driver)); 7962306a36Sopenharmony_ci strscpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), 8062306a36Sopenharmony_ci sizeof(drvinfo->bus_info)); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic u32 dpaa_get_msglevel(struct net_device *net_dev) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci return ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic void dpaa_set_msglevel(struct net_device *net_dev, 8962306a36Sopenharmony_ci u32 msg_enable) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable = msg_enable; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic int dpaa_nway_reset(struct net_device *net_dev) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(net_dev); 9762306a36Sopenharmony_ci struct mac_device *mac_dev = priv->mac_dev; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci return phylink_ethtool_nway_reset(mac_dev->phylink); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic void dpaa_get_pauseparam(struct net_device *net_dev, 10362306a36Sopenharmony_ci struct ethtool_pauseparam *epause) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(net_dev); 10662306a36Sopenharmony_ci struct mac_device *mac_dev = priv->mac_dev; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci phylink_ethtool_get_pauseparam(mac_dev->phylink, epause); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic int dpaa_set_pauseparam(struct net_device *net_dev, 11262306a36Sopenharmony_ci struct ethtool_pauseparam *epause) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(net_dev); 11562306a36Sopenharmony_ci struct mac_device *mac_dev = priv->mac_dev; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return phylink_ethtool_set_pauseparam(mac_dev->phylink, epause); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int dpaa_get_sset_count(struct net_device *net_dev, int type) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci unsigned int total_stats, num_stats; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci num_stats = num_online_cpus() + 1; 12562306a36Sopenharmony_ci total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + 1) + 12662306a36Sopenharmony_ci DPAA_STATS_GLOBAL_LEN; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci switch (type) { 12962306a36Sopenharmony_ci case ETH_SS_STATS: 13062306a36Sopenharmony_ci return total_stats; 13162306a36Sopenharmony_ci default: 13262306a36Sopenharmony_ci return -EOPNOTSUPP; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus, 13762306a36Sopenharmony_ci int crr_cpu, u64 bp_count, u64 *data) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci int num_values = num_cpus + 1; 14062306a36Sopenharmony_ci int crr = 0; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* update current CPU's stats and also add them to the total values */ 14362306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt; 14462306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets; 14762306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets; 15062306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm; 15362306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; 15662306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors; 15962306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors; 16262306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_dropped; 16562306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_dropped; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_dropped; 16862306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_dropped; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci data[crr * num_values + crr_cpu] = bp_count; 17162306a36Sopenharmony_ci data[crr++ * num_values + num_cpus] += bp_count; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic void dpaa_get_ethtool_stats(struct net_device *net_dev, 17562306a36Sopenharmony_ci struct ethtool_stats *stats, u64 *data) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci struct dpaa_percpu_priv *percpu_priv; 17862306a36Sopenharmony_ci struct dpaa_rx_errors rx_errors; 17962306a36Sopenharmony_ci unsigned int num_cpus, offset; 18062306a36Sopenharmony_ci u64 bp_count, cg_time, cg_num; 18162306a36Sopenharmony_ci struct dpaa_ern_cnt ern_cnt; 18262306a36Sopenharmony_ci struct dpaa_bp *dpaa_bp; 18362306a36Sopenharmony_ci struct dpaa_priv *priv; 18462306a36Sopenharmony_ci int total_stats, i; 18562306a36Sopenharmony_ci bool cg_status; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS); 18862306a36Sopenharmony_ci priv = netdev_priv(net_dev); 18962306a36Sopenharmony_ci num_cpus = num_online_cpus(); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci memset(&bp_count, 0, sizeof(bp_count)); 19262306a36Sopenharmony_ci memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors)); 19362306a36Sopenharmony_ci memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt)); 19462306a36Sopenharmony_ci memset(data, 0, total_stats * sizeof(u64)); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci for_each_online_cpu(i) { 19762306a36Sopenharmony_ci percpu_priv = per_cpu_ptr(priv->percpu_priv, i); 19862306a36Sopenharmony_ci dpaa_bp = priv->dpaa_bp; 19962306a36Sopenharmony_ci if (!dpaa_bp->percpu_count) 20062306a36Sopenharmony_ci continue; 20162306a36Sopenharmony_ci bp_count = *(per_cpu_ptr(dpaa_bp->percpu_count, i)); 20262306a36Sopenharmony_ci rx_errors.dme += percpu_priv->rx_errors.dme; 20362306a36Sopenharmony_ci rx_errors.fpe += percpu_priv->rx_errors.fpe; 20462306a36Sopenharmony_ci rx_errors.fse += percpu_priv->rx_errors.fse; 20562306a36Sopenharmony_ci rx_errors.phe += percpu_priv->rx_errors.phe; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; 20862306a36Sopenharmony_ci ern_cnt.wred += percpu_priv->ern_cnt.wred; 20962306a36Sopenharmony_ci ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; 21062306a36Sopenharmony_ci ern_cnt.early_window += percpu_priv->ern_cnt.early_window; 21162306a36Sopenharmony_ci ern_cnt.late_window += percpu_priv->ern_cnt.late_window; 21262306a36Sopenharmony_ci ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; 21362306a36Sopenharmony_ci ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; 21462306a36Sopenharmony_ci ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci copy_stats(percpu_priv, num_cpus, i, bp_count, data); 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + 1); 22062306a36Sopenharmony_ci memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors)); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci offset += sizeof(struct dpaa_rx_errors) / sizeof(u64); 22362306a36Sopenharmony_ci memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt)); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* gather congestion related counters */ 22662306a36Sopenharmony_ci cg_num = 0; 22762306a36Sopenharmony_ci cg_status = false; 22862306a36Sopenharmony_ci cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies); 22962306a36Sopenharmony_ci if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) { 23062306a36Sopenharmony_ci cg_num = priv->cgr_data.cgr_congested_count; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci /* reset congestion stats (like QMan API does */ 23362306a36Sopenharmony_ci priv->cgr_data.congested_jiffies = 0; 23462306a36Sopenharmony_ci priv->cgr_data.cgr_congested_count = 0; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64); 23862306a36Sopenharmony_ci data[offset++] = cg_time; 23962306a36Sopenharmony_ci data[offset++] = cg_num; 24062306a36Sopenharmony_ci data[offset++] = cg_status; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void dpaa_get_strings(struct net_device *net_dev, u32 stringset, 24462306a36Sopenharmony_ci u8 *data) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci unsigned int i, j, num_cpus, size; 24762306a36Sopenharmony_ci char string_cpu[ETH_GSTRING_LEN]; 24862306a36Sopenharmony_ci u8 *strings; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci memset(string_cpu, 0, sizeof(string_cpu)); 25162306a36Sopenharmony_ci strings = data; 25262306a36Sopenharmony_ci num_cpus = num_online_cpus(); 25362306a36Sopenharmony_ci size = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) { 25662306a36Sopenharmony_ci for (j = 0; j < num_cpus; j++) { 25762306a36Sopenharmony_ci snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", 25862306a36Sopenharmony_ci dpaa_stats_percpu[i], j); 25962306a36Sopenharmony_ci memcpy(strings, string_cpu, ETH_GSTRING_LEN); 26062306a36Sopenharmony_ci strings += ETH_GSTRING_LEN; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", 26362306a36Sopenharmony_ci dpaa_stats_percpu[i]); 26462306a36Sopenharmony_ci memcpy(strings, string_cpu, ETH_GSTRING_LEN); 26562306a36Sopenharmony_ci strings += ETH_GSTRING_LEN; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci for (j = 0; j < num_cpus; j++) { 26862306a36Sopenharmony_ci snprintf(string_cpu, ETH_GSTRING_LEN, 26962306a36Sopenharmony_ci "bpool [CPU %d]", j); 27062306a36Sopenharmony_ci memcpy(strings, string_cpu, ETH_GSTRING_LEN); 27162306a36Sopenharmony_ci strings += ETH_GSTRING_LEN; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci snprintf(string_cpu, ETH_GSTRING_LEN, "bpool [TOTAL]"); 27462306a36Sopenharmony_ci memcpy(strings, string_cpu, ETH_GSTRING_LEN); 27562306a36Sopenharmony_ci strings += ETH_GSTRING_LEN; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci memcpy(strings, dpaa_stats_global, size); 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int dpaa_get_hash_opts(struct net_device *dev, 28162306a36Sopenharmony_ci struct ethtool_rxnfc *cmd) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci struct dpaa_priv *priv = netdev_priv(dev); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci cmd->data = 0; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci switch (cmd->flow_type) { 28862306a36Sopenharmony_ci case TCP_V4_FLOW: 28962306a36Sopenharmony_ci case TCP_V6_FLOW: 29062306a36Sopenharmony_ci case UDP_V4_FLOW: 29162306a36Sopenharmony_ci case UDP_V6_FLOW: 29262306a36Sopenharmony_ci if (priv->keygen_in_use) 29362306a36Sopenharmony_ci cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 29462306a36Sopenharmony_ci fallthrough; 29562306a36Sopenharmony_ci case IPV4_FLOW: 29662306a36Sopenharmony_ci case IPV6_FLOW: 29762306a36Sopenharmony_ci case SCTP_V4_FLOW: 29862306a36Sopenharmony_ci case SCTP_V6_FLOW: 29962306a36Sopenharmony_ci case AH_ESP_V4_FLOW: 30062306a36Sopenharmony_ci case AH_ESP_V6_FLOW: 30162306a36Sopenharmony_ci case AH_V4_FLOW: 30262306a36Sopenharmony_ci case AH_V6_FLOW: 30362306a36Sopenharmony_ci case ESP_V4_FLOW: 30462306a36Sopenharmony_ci case ESP_V6_FLOW: 30562306a36Sopenharmony_ci if (priv->keygen_in_use) 30662306a36Sopenharmony_ci cmd->data |= RXH_IP_SRC | RXH_IP_DST; 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci default: 30962306a36Sopenharmony_ci cmd->data = 0; 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return 0; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic int dpaa_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, 31762306a36Sopenharmony_ci u32 *unused) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci int ret = -EOPNOTSUPP; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci switch (cmd->cmd) { 32262306a36Sopenharmony_ci case ETHTOOL_GRXFH: 32362306a36Sopenharmony_ci ret = dpaa_get_hash_opts(dev, cmd); 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci default: 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci return ret; 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic void dpaa_set_hash(struct net_device *net_dev, bool enable) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct mac_device *mac_dev; 33562306a36Sopenharmony_ci struct fman_port *rxport; 33662306a36Sopenharmony_ci struct dpaa_priv *priv; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci priv = netdev_priv(net_dev); 33962306a36Sopenharmony_ci mac_dev = priv->mac_dev; 34062306a36Sopenharmony_ci rxport = mac_dev->port[0]; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci fman_port_use_kg_hash(rxport, enable); 34362306a36Sopenharmony_ci priv->keygen_in_use = enable; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic int dpaa_set_hash_opts(struct net_device *dev, 34762306a36Sopenharmony_ci struct ethtool_rxnfc *nfc) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci int ret = -EINVAL; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* we support hashing on IPv4/v6 src/dest IP and L4 src/dest port */ 35262306a36Sopenharmony_ci if (nfc->data & 35362306a36Sopenharmony_ci ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) 35462306a36Sopenharmony_ci return -EINVAL; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci switch (nfc->flow_type) { 35762306a36Sopenharmony_ci case TCP_V4_FLOW: 35862306a36Sopenharmony_ci case TCP_V6_FLOW: 35962306a36Sopenharmony_ci case UDP_V4_FLOW: 36062306a36Sopenharmony_ci case UDP_V6_FLOW: 36162306a36Sopenharmony_ci case IPV4_FLOW: 36262306a36Sopenharmony_ci case IPV6_FLOW: 36362306a36Sopenharmony_ci case SCTP_V4_FLOW: 36462306a36Sopenharmony_ci case SCTP_V6_FLOW: 36562306a36Sopenharmony_ci case AH_ESP_V4_FLOW: 36662306a36Sopenharmony_ci case AH_ESP_V6_FLOW: 36762306a36Sopenharmony_ci case AH_V4_FLOW: 36862306a36Sopenharmony_ci case AH_V6_FLOW: 36962306a36Sopenharmony_ci case ESP_V4_FLOW: 37062306a36Sopenharmony_ci case ESP_V6_FLOW: 37162306a36Sopenharmony_ci dpaa_set_hash(dev, !!nfc->data); 37262306a36Sopenharmony_ci ret = 0; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci default: 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci return ret; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic int dpaa_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci int ret = -EOPNOTSUPP; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci switch (cmd->cmd) { 38662306a36Sopenharmony_ci case ETHTOOL_SRXFH: 38762306a36Sopenharmony_ci ret = dpaa_set_hash_opts(dev, cmd); 38862306a36Sopenharmony_ci break; 38962306a36Sopenharmony_ci default: 39062306a36Sopenharmony_ci break; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return ret; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int dpaa_get_ts_info(struct net_device *net_dev, 39762306a36Sopenharmony_ci struct ethtool_ts_info *info) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct device *dev = net_dev->dev.parent; 40062306a36Sopenharmony_ci struct device_node *mac_node = dev->of_node; 40162306a36Sopenharmony_ci struct device_node *fman_node = NULL, *ptp_node = NULL; 40262306a36Sopenharmony_ci struct platform_device *ptp_dev = NULL; 40362306a36Sopenharmony_ci struct ptp_qoriq *ptp = NULL; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci info->phc_index = -1; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci fman_node = of_get_parent(mac_node); 40862306a36Sopenharmony_ci if (fman_node) { 40962306a36Sopenharmony_ci ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0); 41062306a36Sopenharmony_ci of_node_put(fman_node); 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (ptp_node) { 41462306a36Sopenharmony_ci ptp_dev = of_find_device_by_node(ptp_node); 41562306a36Sopenharmony_ci of_node_put(ptp_node); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (ptp_dev) 41962306a36Sopenharmony_ci ptp = platform_get_drvdata(ptp_dev); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (ptp) 42262306a36Sopenharmony_ci info->phc_index = ptp->phc_index; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | 42562306a36Sopenharmony_ci SOF_TIMESTAMPING_RX_HARDWARE | 42662306a36Sopenharmony_ci SOF_TIMESTAMPING_RAW_HARDWARE; 42762306a36Sopenharmony_ci info->tx_types = (1 << HWTSTAMP_TX_OFF) | 42862306a36Sopenharmony_ci (1 << HWTSTAMP_TX_ON); 42962306a36Sopenharmony_ci info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 43062306a36Sopenharmony_ci (1 << HWTSTAMP_FILTER_ALL); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int dpaa_get_coalesce(struct net_device *dev, 43662306a36Sopenharmony_ci struct ethtool_coalesce *c, 43762306a36Sopenharmony_ci struct kernel_ethtool_coalesce *kernel_coal, 43862306a36Sopenharmony_ci struct netlink_ext_ack *extack) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct qman_portal *portal; 44162306a36Sopenharmony_ci u32 period; 44262306a36Sopenharmony_ci u8 thresh; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci portal = qman_get_affine_portal(smp_processor_id()); 44562306a36Sopenharmony_ci qman_portal_get_iperiod(portal, &period); 44662306a36Sopenharmony_ci qman_dqrr_get_ithresh(portal, &thresh); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci c->rx_coalesce_usecs = period; 44962306a36Sopenharmony_ci c->rx_max_coalesced_frames = thresh; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci return 0; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic int dpaa_set_coalesce(struct net_device *dev, 45562306a36Sopenharmony_ci struct ethtool_coalesce *c, 45662306a36Sopenharmony_ci struct kernel_ethtool_coalesce *kernel_coal, 45762306a36Sopenharmony_ci struct netlink_ext_ack *extack) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci const cpumask_t *cpus = qman_affine_cpus(); 46062306a36Sopenharmony_ci bool needs_revert[NR_CPUS] = {false}; 46162306a36Sopenharmony_ci struct qman_portal *portal; 46262306a36Sopenharmony_ci u32 period, prev_period; 46362306a36Sopenharmony_ci u8 thresh, prev_thresh; 46462306a36Sopenharmony_ci int cpu, res; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci period = c->rx_coalesce_usecs; 46762306a36Sopenharmony_ci thresh = c->rx_max_coalesced_frames; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* save previous values */ 47062306a36Sopenharmony_ci portal = qman_get_affine_portal(smp_processor_id()); 47162306a36Sopenharmony_ci qman_portal_get_iperiod(portal, &prev_period); 47262306a36Sopenharmony_ci qman_dqrr_get_ithresh(portal, &prev_thresh); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* set new values */ 47562306a36Sopenharmony_ci for_each_cpu_and(cpu, cpus, cpu_online_mask) { 47662306a36Sopenharmony_ci portal = qman_get_affine_portal(cpu); 47762306a36Sopenharmony_ci res = qman_portal_set_iperiod(portal, period); 47862306a36Sopenharmony_ci if (res) 47962306a36Sopenharmony_ci goto revert_values; 48062306a36Sopenharmony_ci res = qman_dqrr_set_ithresh(portal, thresh); 48162306a36Sopenharmony_ci if (res) { 48262306a36Sopenharmony_ci qman_portal_set_iperiod(portal, prev_period); 48362306a36Sopenharmony_ci goto revert_values; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci needs_revert[cpu] = true; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci return 0; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cirevert_values: 49162306a36Sopenharmony_ci /* restore previous values */ 49262306a36Sopenharmony_ci for_each_cpu_and(cpu, cpus, cpu_online_mask) { 49362306a36Sopenharmony_ci if (!needs_revert[cpu]) 49462306a36Sopenharmony_ci continue; 49562306a36Sopenharmony_ci portal = qman_get_affine_portal(cpu); 49662306a36Sopenharmony_ci /* previous values will not fail, ignore return value */ 49762306a36Sopenharmony_ci qman_portal_set_iperiod(portal, prev_period); 49862306a36Sopenharmony_ci qman_dqrr_set_ithresh(portal, prev_thresh); 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci return res; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ciconst struct ethtool_ops dpaa_ethtool_ops = { 50562306a36Sopenharmony_ci .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | 50662306a36Sopenharmony_ci ETHTOOL_COALESCE_RX_MAX_FRAMES, 50762306a36Sopenharmony_ci .get_drvinfo = dpaa_get_drvinfo, 50862306a36Sopenharmony_ci .get_msglevel = dpaa_get_msglevel, 50962306a36Sopenharmony_ci .set_msglevel = dpaa_set_msglevel, 51062306a36Sopenharmony_ci .nway_reset = dpaa_nway_reset, 51162306a36Sopenharmony_ci .get_pauseparam = dpaa_get_pauseparam, 51262306a36Sopenharmony_ci .set_pauseparam = dpaa_set_pauseparam, 51362306a36Sopenharmony_ci .get_link = ethtool_op_get_link, 51462306a36Sopenharmony_ci .get_sset_count = dpaa_get_sset_count, 51562306a36Sopenharmony_ci .get_ethtool_stats = dpaa_get_ethtool_stats, 51662306a36Sopenharmony_ci .get_strings = dpaa_get_strings, 51762306a36Sopenharmony_ci .get_link_ksettings = dpaa_get_link_ksettings, 51862306a36Sopenharmony_ci .set_link_ksettings = dpaa_set_link_ksettings, 51962306a36Sopenharmony_ci .get_rxnfc = dpaa_get_rxnfc, 52062306a36Sopenharmony_ci .set_rxnfc = dpaa_set_rxnfc, 52162306a36Sopenharmony_ci .get_ts_info = dpaa_get_ts_info, 52262306a36Sopenharmony_ci .get_coalesce = dpaa_get_coalesce, 52362306a36Sopenharmony_ci .set_coalesce = dpaa_set_coalesce, 52462306a36Sopenharmony_ci}; 525