1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21edb9ca6SSiva Reddy /* 10G controller driver for Samsung SoCs 31edb9ca6SSiva Reddy * 41edb9ca6SSiva Reddy * Copyright (C) 2013 Samsung Electronics Co., Ltd. 51edb9ca6SSiva Reddy * http://www.samsung.com 61edb9ca6SSiva Reddy * 71edb9ca6SSiva Reddy * Author: Siva Reddy Kallam <siva.kallam@samsung.com> 81edb9ca6SSiva Reddy */ 91edb9ca6SSiva Reddy 101edb9ca6SSiva Reddy #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 111edb9ca6SSiva Reddy 1225f72a74SVipul Pandya #include <linux/clk.h> 1325f72a74SVipul Pandya #include <linux/interrupt.h> 141edb9ca6SSiva Reddy #include <linux/kernel.h> 151edb9ca6SSiva Reddy #include <linux/netdevice.h> 1625f72a74SVipul Pandya #include <linux/net_tstamp.h> 171edb9ca6SSiva Reddy #include <linux/phy.h> 1825f72a74SVipul Pandya #include <linux/ptp_clock_kernel.h> 191edb9ca6SSiva Reddy 201edb9ca6SSiva Reddy #include "sxgbe_common.h" 2125f72a74SVipul Pandya #include "sxgbe_reg.h" 2225f72a74SVipul Pandya #include "sxgbe_dma.h" 231edb9ca6SSiva Reddy 241edb9ca6SSiva Reddy struct sxgbe_stats { 251edb9ca6SSiva Reddy char stat_string[ETH_GSTRING_LEN]; 261edb9ca6SSiva Reddy int sizeof_stat; 271edb9ca6SSiva Reddy int stat_offset; 281edb9ca6SSiva Reddy }; 291edb9ca6SSiva Reddy 301edb9ca6SSiva Reddy #define SXGBE_STAT(m) \ 311edb9ca6SSiva Reddy { \ 321edb9ca6SSiva Reddy #m, \ 33c593642cSPankaj Bharadiya sizeof_field(struct sxgbe_extra_stats, m), \ 341edb9ca6SSiva Reddy offsetof(struct sxgbe_priv_data, xstats.m) \ 351edb9ca6SSiva Reddy } 361edb9ca6SSiva Reddy 371edb9ca6SSiva Reddy static const struct sxgbe_stats sxgbe_gstrings_stats[] = { 3825f72a74SVipul Pandya /* TX/RX IRQ events */ 3925f72a74SVipul Pandya SXGBE_STAT(tx_process_stopped_irq), 4025f72a74SVipul Pandya SXGBE_STAT(tx_ctxt_desc_err), 4125f72a74SVipul Pandya SXGBE_STAT(tx_threshold), 4225f72a74SVipul Pandya SXGBE_STAT(rx_threshold), 4325f72a74SVipul Pandya SXGBE_STAT(tx_pkt_n), 4425f72a74SVipul Pandya SXGBE_STAT(rx_pkt_n), 4525f72a74SVipul Pandya SXGBE_STAT(normal_irq_n), 4625f72a74SVipul Pandya SXGBE_STAT(tx_normal_irq_n), 4725f72a74SVipul Pandya SXGBE_STAT(rx_normal_irq_n), 4825f72a74SVipul Pandya SXGBE_STAT(napi_poll), 4925f72a74SVipul Pandya SXGBE_STAT(tx_clean), 5025f72a74SVipul Pandya SXGBE_STAT(tx_reset_ic_bit), 5125f72a74SVipul Pandya SXGBE_STAT(rx_process_stopped_irq), 5225f72a74SVipul Pandya SXGBE_STAT(rx_underflow_irq), 5325f72a74SVipul Pandya 5425f72a74SVipul Pandya /* Bus access errors */ 5525f72a74SVipul Pandya SXGBE_STAT(fatal_bus_error_irq), 5625f72a74SVipul Pandya SXGBE_STAT(tx_read_transfer_err), 5725f72a74SVipul Pandya SXGBE_STAT(tx_write_transfer_err), 5825f72a74SVipul Pandya SXGBE_STAT(tx_desc_access_err), 5925f72a74SVipul Pandya SXGBE_STAT(tx_buffer_access_err), 6025f72a74SVipul Pandya SXGBE_STAT(tx_data_transfer_err), 6125f72a74SVipul Pandya SXGBE_STAT(rx_read_transfer_err), 6225f72a74SVipul Pandya SXGBE_STAT(rx_write_transfer_err), 6325f72a74SVipul Pandya SXGBE_STAT(rx_desc_access_err), 6425f72a74SVipul Pandya SXGBE_STAT(rx_buffer_access_err), 6525f72a74SVipul Pandya SXGBE_STAT(rx_data_transfer_err), 6625f72a74SVipul Pandya 6725f72a74SVipul Pandya /* EEE-LPI stats */ 68acc18c14SGirish K S SXGBE_STAT(tx_lpi_entry_n), 69acc18c14SGirish K S SXGBE_STAT(tx_lpi_exit_n), 70acc18c14SGirish K S SXGBE_STAT(rx_lpi_entry_n), 71acc18c14SGirish K S SXGBE_STAT(rx_lpi_exit_n), 72acc18c14SGirish K S SXGBE_STAT(eee_wakeup_error_n), 7325f72a74SVipul Pandya 7425f72a74SVipul Pandya /* RX specific */ 7525f72a74SVipul Pandya /* L2 error */ 7625f72a74SVipul Pandya SXGBE_STAT(rx_code_gmii_err), 7725f72a74SVipul Pandya SXGBE_STAT(rx_watchdog_err), 7825f72a74SVipul Pandya SXGBE_STAT(rx_crc_err), 7925f72a74SVipul Pandya SXGBE_STAT(rx_gaint_pkt_err), 8025f72a74SVipul Pandya SXGBE_STAT(ip_hdr_err), 8125f72a74SVipul Pandya SXGBE_STAT(ip_payload_err), 8225f72a74SVipul Pandya SXGBE_STAT(overflow_error), 8325f72a74SVipul Pandya 8425f72a74SVipul Pandya /* L2 Pkt type */ 8525f72a74SVipul Pandya SXGBE_STAT(len_pkt), 8625f72a74SVipul Pandya SXGBE_STAT(mac_ctl_pkt), 8725f72a74SVipul Pandya SXGBE_STAT(dcb_ctl_pkt), 8825f72a74SVipul Pandya SXGBE_STAT(arp_pkt), 8925f72a74SVipul Pandya SXGBE_STAT(oam_pkt), 9025f72a74SVipul Pandya SXGBE_STAT(untag_okt), 9125f72a74SVipul Pandya SXGBE_STAT(other_pkt), 9225f72a74SVipul Pandya SXGBE_STAT(svlan_tag_pkt), 9325f72a74SVipul Pandya SXGBE_STAT(cvlan_tag_pkt), 9425f72a74SVipul Pandya SXGBE_STAT(dvlan_ocvlan_icvlan_pkt), 9525f72a74SVipul Pandya SXGBE_STAT(dvlan_osvlan_isvlan_pkt), 9625f72a74SVipul Pandya SXGBE_STAT(dvlan_osvlan_icvlan_pkt), 9725f72a74SVipul Pandya SXGBE_STAT(dvan_ocvlan_icvlan_pkt), 9825f72a74SVipul Pandya 9925f72a74SVipul Pandya /* L3/L4 Pkt type */ 10025f72a74SVipul Pandya SXGBE_STAT(not_ip_pkt), 10125f72a74SVipul Pandya SXGBE_STAT(ip4_tcp_pkt), 10225f72a74SVipul Pandya SXGBE_STAT(ip4_udp_pkt), 10325f72a74SVipul Pandya SXGBE_STAT(ip4_icmp_pkt), 10425f72a74SVipul Pandya SXGBE_STAT(ip4_unknown_pkt), 10525f72a74SVipul Pandya SXGBE_STAT(ip6_tcp_pkt), 10625f72a74SVipul Pandya SXGBE_STAT(ip6_udp_pkt), 10725f72a74SVipul Pandya SXGBE_STAT(ip6_icmp_pkt), 10825f72a74SVipul Pandya SXGBE_STAT(ip6_unknown_pkt), 10925f72a74SVipul Pandya 11025f72a74SVipul Pandya /* Filter specific */ 11125f72a74SVipul Pandya SXGBE_STAT(vlan_filter_match), 11225f72a74SVipul Pandya SXGBE_STAT(sa_filter_fail), 11325f72a74SVipul Pandya SXGBE_STAT(da_filter_fail), 11425f72a74SVipul Pandya SXGBE_STAT(hash_filter_pass), 11525f72a74SVipul Pandya SXGBE_STAT(l3_filter_match), 11625f72a74SVipul Pandya SXGBE_STAT(l4_filter_match), 11725f72a74SVipul Pandya 11825f72a74SVipul Pandya /* RX context specific */ 11925f72a74SVipul Pandya SXGBE_STAT(timestamp_dropped), 12025f72a74SVipul Pandya SXGBE_STAT(rx_msg_type_no_ptp), 12125f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_sync), 12225f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_follow_up), 12325f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_delay_req), 12425f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_delay_resp), 12525f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_pdelay_req), 12625f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_pdelay_resp), 12725f72a74SVipul Pandya SXGBE_STAT(rx_ptp_type_pdelay_follow_up), 12825f72a74SVipul Pandya SXGBE_STAT(rx_ptp_announce), 12925f72a74SVipul Pandya SXGBE_STAT(rx_ptp_mgmt), 13025f72a74SVipul Pandya SXGBE_STAT(rx_ptp_signal), 13125f72a74SVipul Pandya SXGBE_STAT(rx_ptp_resv_msg_type), 1321edb9ca6SSiva Reddy }; 1331edb9ca6SSiva Reddy #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats) 1341edb9ca6SSiva Reddy 135acc18c14SGirish K S static int sxgbe_get_eee(struct net_device *dev, 136acc18c14SGirish K S struct ethtool_eee *edata) 137acc18c14SGirish K S { 138acc18c14SGirish K S struct sxgbe_priv_data *priv = netdev_priv(dev); 139acc18c14SGirish K S 140acc18c14SGirish K S if (!priv->hw_cap.eee) 141acc18c14SGirish K S return -EOPNOTSUPP; 142acc18c14SGirish K S 143acc18c14SGirish K S edata->eee_enabled = priv->eee_enabled; 144acc18c14SGirish K S edata->eee_active = priv->eee_active; 145acc18c14SGirish K S edata->tx_lpi_timer = priv->tx_lpi_timer; 146acc18c14SGirish K S 1472ebc440aSPhilippe Reynes return phy_ethtool_get_eee(dev->phydev, edata); 148acc18c14SGirish K S } 149acc18c14SGirish K S 150acc18c14SGirish K S static int sxgbe_set_eee(struct net_device *dev, 151acc18c14SGirish K S struct ethtool_eee *edata) 152acc18c14SGirish K S { 153acc18c14SGirish K S struct sxgbe_priv_data *priv = netdev_priv(dev); 154acc18c14SGirish K S 155acc18c14SGirish K S priv->eee_enabled = edata->eee_enabled; 156acc18c14SGirish K S 157acc18c14SGirish K S if (!priv->eee_enabled) { 158acc18c14SGirish K S sxgbe_disable_eee_mode(priv); 159acc18c14SGirish K S } else { 160acc18c14SGirish K S /* We are asking for enabling the EEE but it is safe 161acc18c14SGirish K S * to verify all by invoking the eee_init function. 162acc18c14SGirish K S * In case of failure it will return an error. 163acc18c14SGirish K S */ 164acc18c14SGirish K S priv->eee_enabled = sxgbe_eee_init(priv); 165acc18c14SGirish K S if (!priv->eee_enabled) 166acc18c14SGirish K S return -EOPNOTSUPP; 167acc18c14SGirish K S 168acc18c14SGirish K S /* Do not change tx_lpi_timer in case of failure */ 169acc18c14SGirish K S priv->tx_lpi_timer = edata->tx_lpi_timer; 170acc18c14SGirish K S } 171acc18c14SGirish K S 1722ebc440aSPhilippe Reynes return phy_ethtool_set_eee(dev->phydev, edata); 173acc18c14SGirish K S } 174acc18c14SGirish K S 17525f72a74SVipul Pandya static void sxgbe_getdrvinfo(struct net_device *dev, 17625f72a74SVipul Pandya struct ethtool_drvinfo *info) 17725f72a74SVipul Pandya { 17825f72a74SVipul Pandya strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); 17925f72a74SVipul Pandya strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 18025f72a74SVipul Pandya } 18125f72a74SVipul Pandya 18225f72a74SVipul Pandya static u32 sxgbe_getmsglevel(struct net_device *dev) 18325f72a74SVipul Pandya { 18425f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 18525f72a74SVipul Pandya return priv->msg_enable; 18625f72a74SVipul Pandya } 18725f72a74SVipul Pandya 18825f72a74SVipul Pandya static void sxgbe_setmsglevel(struct net_device *dev, u32 level) 18925f72a74SVipul Pandya { 19025f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 19125f72a74SVipul Pandya priv->msg_enable = level; 19225f72a74SVipul Pandya } 19325f72a74SVipul Pandya 19425f72a74SVipul Pandya static void sxgbe_get_strings(struct net_device *dev, u32 stringset, u8 *data) 19525f72a74SVipul Pandya { 19625f72a74SVipul Pandya int i; 19725f72a74SVipul Pandya u8 *p = data; 19825f72a74SVipul Pandya 19925f72a74SVipul Pandya switch (stringset) { 20025f72a74SVipul Pandya case ETH_SS_STATS: 20125f72a74SVipul Pandya for (i = 0; i < SXGBE_STATS_LEN; i++) { 20225f72a74SVipul Pandya memcpy(p, sxgbe_gstrings_stats[i].stat_string, 20325f72a74SVipul Pandya ETH_GSTRING_LEN); 20425f72a74SVipul Pandya p += ETH_GSTRING_LEN; 20525f72a74SVipul Pandya } 20625f72a74SVipul Pandya break; 20725f72a74SVipul Pandya default: 20825f72a74SVipul Pandya WARN_ON(1); 20925f72a74SVipul Pandya break; 21025f72a74SVipul Pandya } 21125f72a74SVipul Pandya } 21225f72a74SVipul Pandya 21325f72a74SVipul Pandya static int sxgbe_get_sset_count(struct net_device *netdev, int sset) 21425f72a74SVipul Pandya { 21525f72a74SVipul Pandya int len; 21625f72a74SVipul Pandya 21725f72a74SVipul Pandya switch (sset) { 21825f72a74SVipul Pandya case ETH_SS_STATS: 21925f72a74SVipul Pandya len = SXGBE_STATS_LEN; 22025f72a74SVipul Pandya return len; 22125f72a74SVipul Pandya default: 22225f72a74SVipul Pandya return -EINVAL; 22325f72a74SVipul Pandya } 22425f72a74SVipul Pandya } 22525f72a74SVipul Pandya 22625f72a74SVipul Pandya static void sxgbe_get_ethtool_stats(struct net_device *dev, 22725f72a74SVipul Pandya struct ethtool_stats *dummy, u64 *data) 22825f72a74SVipul Pandya { 22925f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 23025f72a74SVipul Pandya int i; 23125f72a74SVipul Pandya char *p; 23225f72a74SVipul Pandya 23325f72a74SVipul Pandya if (priv->eee_enabled) { 2342ebc440aSPhilippe Reynes int val = phy_get_eee_err(dev->phydev); 23525f72a74SVipul Pandya 23625f72a74SVipul Pandya if (val) 23725f72a74SVipul Pandya priv->xstats.eee_wakeup_error_n = val; 23825f72a74SVipul Pandya } 23925f72a74SVipul Pandya 24025f72a74SVipul Pandya for (i = 0; i < SXGBE_STATS_LEN; i++) { 24125f72a74SVipul Pandya p = (char *)priv + sxgbe_gstrings_stats[i].stat_offset; 24225f72a74SVipul Pandya data[i] = (sxgbe_gstrings_stats[i].sizeof_stat == sizeof(u64)) 24325f72a74SVipul Pandya ? (*(u64 *)p) : (*(u32 *)p); 24425f72a74SVipul Pandya } 24525f72a74SVipul Pandya } 24625f72a74SVipul Pandya 24725f72a74SVipul Pandya static void sxgbe_get_channels(struct net_device *dev, 24825f72a74SVipul Pandya struct ethtool_channels *channel) 24925f72a74SVipul Pandya { 25025f72a74SVipul Pandya channel->max_rx = SXGBE_MAX_RX_CHANNELS; 25125f72a74SVipul Pandya channel->max_tx = SXGBE_MAX_TX_CHANNELS; 25225f72a74SVipul Pandya channel->rx_count = SXGBE_RX_QUEUES; 25325f72a74SVipul Pandya channel->tx_count = SXGBE_TX_QUEUES; 25425f72a74SVipul Pandya } 25525f72a74SVipul Pandya 25625f72a74SVipul Pandya static u32 sxgbe_riwt2usec(u32 riwt, struct sxgbe_priv_data *priv) 25725f72a74SVipul Pandya { 25825f72a74SVipul Pandya unsigned long clk = clk_get_rate(priv->sxgbe_clk); 25925f72a74SVipul Pandya 26025f72a74SVipul Pandya if (!clk) 26125f72a74SVipul Pandya return 0; 26225f72a74SVipul Pandya 26325f72a74SVipul Pandya return (riwt * 256) / (clk / 1000000); 26425f72a74SVipul Pandya } 26525f72a74SVipul Pandya 26625f72a74SVipul Pandya static u32 sxgbe_usec2riwt(u32 usec, struct sxgbe_priv_data *priv) 26725f72a74SVipul Pandya { 26825f72a74SVipul Pandya unsigned long clk = clk_get_rate(priv->sxgbe_clk); 26925f72a74SVipul Pandya 27025f72a74SVipul Pandya if (!clk) 27125f72a74SVipul Pandya return 0; 27225f72a74SVipul Pandya 27325f72a74SVipul Pandya return (usec * (clk / 1000000)) / 256; 27425f72a74SVipul Pandya } 27525f72a74SVipul Pandya 27625f72a74SVipul Pandya static int sxgbe_get_coalesce(struct net_device *dev, 27725f72a74SVipul Pandya struct ethtool_coalesce *ec) 27825f72a74SVipul Pandya { 27925f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 28025f72a74SVipul Pandya 28125f72a74SVipul Pandya if (priv->use_riwt) 28225f72a74SVipul Pandya ec->rx_coalesce_usecs = sxgbe_riwt2usec(priv->rx_riwt, priv); 28325f72a74SVipul Pandya 28425f72a74SVipul Pandya return 0; 28525f72a74SVipul Pandya } 28625f72a74SVipul Pandya 28725f72a74SVipul Pandya static int sxgbe_set_coalesce(struct net_device *dev, 28825f72a74SVipul Pandya struct ethtool_coalesce *ec) 28925f72a74SVipul Pandya { 29025f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 29125f72a74SVipul Pandya unsigned int rx_riwt; 29225f72a74SVipul Pandya 29325f72a74SVipul Pandya if (!ec->rx_coalesce_usecs) 29425f72a74SVipul Pandya return -EINVAL; 29525f72a74SVipul Pandya 29625f72a74SVipul Pandya rx_riwt = sxgbe_usec2riwt(ec->rx_coalesce_usecs, priv); 29725f72a74SVipul Pandya 29825f72a74SVipul Pandya if ((rx_riwt > SXGBE_MAX_DMA_RIWT) || (rx_riwt < SXGBE_MIN_DMA_RIWT)) 29925f72a74SVipul Pandya return -EINVAL; 30025f72a74SVipul Pandya else if (!priv->use_riwt) 30125f72a74SVipul Pandya return -EOPNOTSUPP; 30225f72a74SVipul Pandya 30325f72a74SVipul Pandya priv->rx_riwt = rx_riwt; 30425f72a74SVipul Pandya priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); 30525f72a74SVipul Pandya 30625f72a74SVipul Pandya return 0; 30725f72a74SVipul Pandya } 30825f72a74SVipul Pandya 30925f72a74SVipul Pandya static int sxgbe_get_rss_hash_opts(struct sxgbe_priv_data *priv, 31025f72a74SVipul Pandya struct ethtool_rxnfc *cmd) 31125f72a74SVipul Pandya { 31225f72a74SVipul Pandya cmd->data = 0; 31325f72a74SVipul Pandya 31425f72a74SVipul Pandya /* Report default options for RSS on sxgbe */ 31525f72a74SVipul Pandya switch (cmd->flow_type) { 31625f72a74SVipul Pandya case TCP_V4_FLOW: 31725f72a74SVipul Pandya case UDP_V4_FLOW: 31825f72a74SVipul Pandya cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 319*df561f66SGustavo A. R. Silva fallthrough; 32025f72a74SVipul Pandya case SCTP_V4_FLOW: 32125f72a74SVipul Pandya case AH_ESP_V4_FLOW: 32225f72a74SVipul Pandya case AH_V4_FLOW: 32325f72a74SVipul Pandya case ESP_V4_FLOW: 32425f72a74SVipul Pandya case IPV4_FLOW: 32525f72a74SVipul Pandya cmd->data |= RXH_IP_SRC | RXH_IP_DST; 32625f72a74SVipul Pandya break; 32725f72a74SVipul Pandya case TCP_V6_FLOW: 32825f72a74SVipul Pandya case UDP_V6_FLOW: 32925f72a74SVipul Pandya cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 330*df561f66SGustavo A. R. Silva fallthrough; 33125f72a74SVipul Pandya case SCTP_V6_FLOW: 33225f72a74SVipul Pandya case AH_ESP_V6_FLOW: 33325f72a74SVipul Pandya case AH_V6_FLOW: 33425f72a74SVipul Pandya case ESP_V6_FLOW: 33525f72a74SVipul Pandya case IPV6_FLOW: 33625f72a74SVipul Pandya cmd->data |= RXH_IP_SRC | RXH_IP_DST; 33725f72a74SVipul Pandya break; 33825f72a74SVipul Pandya default: 33925f72a74SVipul Pandya return -EINVAL; 34025f72a74SVipul Pandya } 34125f72a74SVipul Pandya 34225f72a74SVipul Pandya return 0; 34325f72a74SVipul Pandya } 34425f72a74SVipul Pandya 34525f72a74SVipul Pandya static int sxgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, 34625f72a74SVipul Pandya u32 *rule_locs) 34725f72a74SVipul Pandya { 34825f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 34925f72a74SVipul Pandya int ret = -EOPNOTSUPP; 35025f72a74SVipul Pandya 35125f72a74SVipul Pandya switch (cmd->cmd) { 35225f72a74SVipul Pandya case ETHTOOL_GRXFH: 35325f72a74SVipul Pandya ret = sxgbe_get_rss_hash_opts(priv, cmd); 35425f72a74SVipul Pandya break; 35525f72a74SVipul Pandya default: 35625f72a74SVipul Pandya break; 35725f72a74SVipul Pandya } 35825f72a74SVipul Pandya 35925f72a74SVipul Pandya return ret; 36025f72a74SVipul Pandya } 36125f72a74SVipul Pandya 36225f72a74SVipul Pandya static int sxgbe_set_rss_hash_opt(struct sxgbe_priv_data *priv, 36325f72a74SVipul Pandya struct ethtool_rxnfc *cmd) 36425f72a74SVipul Pandya { 36525f72a74SVipul Pandya u32 reg_val = 0; 36625f72a74SVipul Pandya 36725f72a74SVipul Pandya /* RSS does not support anything other than hashing 36825f72a74SVipul Pandya * to queues on src and dst IPs and ports 36925f72a74SVipul Pandya */ 37025f72a74SVipul Pandya if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | 37125f72a74SVipul Pandya RXH_L4_B_0_1 | RXH_L4_B_2_3)) 37225f72a74SVipul Pandya return -EINVAL; 37325f72a74SVipul Pandya 37425f72a74SVipul Pandya switch (cmd->flow_type) { 37525f72a74SVipul Pandya case TCP_V4_FLOW: 37625f72a74SVipul Pandya case TCP_V6_FLOW: 37725f72a74SVipul Pandya if (!(cmd->data & RXH_IP_SRC) || 37825f72a74SVipul Pandya !(cmd->data & RXH_IP_DST) || 37925f72a74SVipul Pandya !(cmd->data & RXH_L4_B_0_1) || 38025f72a74SVipul Pandya !(cmd->data & RXH_L4_B_2_3)) 38125f72a74SVipul Pandya return -EINVAL; 38225f72a74SVipul Pandya reg_val = SXGBE_CORE_RSS_CTL_TCP4TE; 38325f72a74SVipul Pandya break; 38425f72a74SVipul Pandya case UDP_V4_FLOW: 38525f72a74SVipul Pandya case UDP_V6_FLOW: 38625f72a74SVipul Pandya if (!(cmd->data & RXH_IP_SRC) || 38725f72a74SVipul Pandya !(cmd->data & RXH_IP_DST) || 38825f72a74SVipul Pandya !(cmd->data & RXH_L4_B_0_1) || 38925f72a74SVipul Pandya !(cmd->data & RXH_L4_B_2_3)) 39025f72a74SVipul Pandya return -EINVAL; 39125f72a74SVipul Pandya reg_val = SXGBE_CORE_RSS_CTL_UDP4TE; 39225f72a74SVipul Pandya break; 39325f72a74SVipul Pandya case SCTP_V4_FLOW: 39425f72a74SVipul Pandya case AH_ESP_V4_FLOW: 39525f72a74SVipul Pandya case AH_V4_FLOW: 39625f72a74SVipul Pandya case ESP_V4_FLOW: 39725f72a74SVipul Pandya case AH_ESP_V6_FLOW: 39825f72a74SVipul Pandya case AH_V6_FLOW: 39925f72a74SVipul Pandya case ESP_V6_FLOW: 40025f72a74SVipul Pandya case SCTP_V6_FLOW: 40125f72a74SVipul Pandya case IPV4_FLOW: 40225f72a74SVipul Pandya case IPV6_FLOW: 40325f72a74SVipul Pandya if (!(cmd->data & RXH_IP_SRC) || 40425f72a74SVipul Pandya !(cmd->data & RXH_IP_DST) || 40525f72a74SVipul Pandya (cmd->data & RXH_L4_B_0_1) || 40625f72a74SVipul Pandya (cmd->data & RXH_L4_B_2_3)) 40725f72a74SVipul Pandya return -EINVAL; 40825f72a74SVipul Pandya reg_val = SXGBE_CORE_RSS_CTL_IP2TE; 40925f72a74SVipul Pandya break; 41025f72a74SVipul Pandya default: 41125f72a74SVipul Pandya return -EINVAL; 41225f72a74SVipul Pandya } 41325f72a74SVipul Pandya 41425f72a74SVipul Pandya /* Read SXGBE RSS control register and update */ 41525f72a74SVipul Pandya reg_val |= readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); 41625f72a74SVipul Pandya writel(reg_val, priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); 41725f72a74SVipul Pandya readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG); 41825f72a74SVipul Pandya 41925f72a74SVipul Pandya return 0; 42025f72a74SVipul Pandya } 42125f72a74SVipul Pandya 42225f72a74SVipul Pandya static int sxgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 42325f72a74SVipul Pandya { 42425f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 42525f72a74SVipul Pandya int ret = -EOPNOTSUPP; 42625f72a74SVipul Pandya 42725f72a74SVipul Pandya switch (cmd->cmd) { 42825f72a74SVipul Pandya case ETHTOOL_SRXFH: 42925f72a74SVipul Pandya ret = sxgbe_set_rss_hash_opt(priv, cmd); 43025f72a74SVipul Pandya break; 43125f72a74SVipul Pandya default: 43225f72a74SVipul Pandya break; 43325f72a74SVipul Pandya } 43425f72a74SVipul Pandya 43525f72a74SVipul Pandya return ret; 43625f72a74SVipul Pandya } 43725f72a74SVipul Pandya 43825f72a74SVipul Pandya static void sxgbe_get_regs(struct net_device *dev, 43925f72a74SVipul Pandya struct ethtool_regs *regs, void *space) 44025f72a74SVipul Pandya { 44125f72a74SVipul Pandya struct sxgbe_priv_data *priv = netdev_priv(dev); 44225f72a74SVipul Pandya u32 *reg_space = (u32 *)space; 44325f72a74SVipul Pandya int reg_offset; 44425f72a74SVipul Pandya int reg_ix = 0; 44525f72a74SVipul Pandya void __iomem *ioaddr = priv->ioaddr; 44625f72a74SVipul Pandya 44725f72a74SVipul Pandya memset(reg_space, 0x0, REG_SPACE_SIZE); 44825f72a74SVipul Pandya 44925f72a74SVipul Pandya /* MAC registers */ 45025f72a74SVipul Pandya for (reg_offset = START_MAC_REG_OFFSET; 45125f72a74SVipul Pandya reg_offset <= MAX_MAC_REG_OFFSET; reg_offset += 4) { 45225f72a74SVipul Pandya reg_space[reg_ix] = readl(ioaddr + reg_offset); 45325f72a74SVipul Pandya reg_ix++; 45425f72a74SVipul Pandya } 45525f72a74SVipul Pandya 45625f72a74SVipul Pandya /* MTL registers */ 45725f72a74SVipul Pandya for (reg_offset = START_MTL_REG_OFFSET; 45825f72a74SVipul Pandya reg_offset <= MAX_MTL_REG_OFFSET; reg_offset += 4) { 45925f72a74SVipul Pandya reg_space[reg_ix] = readl(ioaddr + reg_offset); 46025f72a74SVipul Pandya reg_ix++; 46125f72a74SVipul Pandya } 46225f72a74SVipul Pandya 46325f72a74SVipul Pandya /* DMA registers */ 46425f72a74SVipul Pandya for (reg_offset = START_DMA_REG_OFFSET; 46525f72a74SVipul Pandya reg_offset <= MAX_DMA_REG_OFFSET; reg_offset += 4) { 46625f72a74SVipul Pandya reg_space[reg_ix] = readl(ioaddr + reg_offset); 46725f72a74SVipul Pandya reg_ix++; 46825f72a74SVipul Pandya } 46925f72a74SVipul Pandya 47025f72a74SVipul Pandya BUG_ON(reg_ix * 4 > REG_SPACE_SIZE); 47125f72a74SVipul Pandya } 47225f72a74SVipul Pandya 47325f72a74SVipul Pandya static int sxgbe_get_regs_len(struct net_device *dev) 47425f72a74SVipul Pandya { 47525f72a74SVipul Pandya return REG_SPACE_SIZE; 47625f72a74SVipul Pandya } 47725f72a74SVipul Pandya 4781edb9ca6SSiva Reddy static const struct ethtool_ops sxgbe_ethtool_ops = { 47919d9ec99SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS, 48025f72a74SVipul Pandya .get_drvinfo = sxgbe_getdrvinfo, 48125f72a74SVipul Pandya .get_msglevel = sxgbe_getmsglevel, 48225f72a74SVipul Pandya .set_msglevel = sxgbe_setmsglevel, 48325f72a74SVipul Pandya .get_link = ethtool_op_get_link, 48425f72a74SVipul Pandya .get_strings = sxgbe_get_strings, 48525f72a74SVipul Pandya .get_ethtool_stats = sxgbe_get_ethtool_stats, 48625f72a74SVipul Pandya .get_sset_count = sxgbe_get_sset_count, 48725f72a74SVipul Pandya .get_channels = sxgbe_get_channels, 48825f72a74SVipul Pandya .get_coalesce = sxgbe_get_coalesce, 48925f72a74SVipul Pandya .set_coalesce = sxgbe_set_coalesce, 49025f72a74SVipul Pandya .get_rxnfc = sxgbe_get_rxnfc, 49125f72a74SVipul Pandya .set_rxnfc = sxgbe_set_rxnfc, 49225f72a74SVipul Pandya .get_regs = sxgbe_get_regs, 49325f72a74SVipul Pandya .get_regs_len = sxgbe_get_regs_len, 494acc18c14SGirish K S .get_eee = sxgbe_get_eee, 495acc18c14SGirish K S .set_eee = sxgbe_set_eee, 49613e4c230SPhilippe Reynes .get_link_ksettings = phy_ethtool_get_link_ksettings, 49713e4c230SPhilippe Reynes .set_link_ksettings = phy_ethtool_set_link_ksettings, 4981edb9ca6SSiva Reddy }; 4991edb9ca6SSiva Reddy 5001edb9ca6SSiva Reddy void sxgbe_set_ethtool_ops(struct net_device *netdev) 5011edb9ca6SSiva Reddy { 5027ad24ea4SWilfried Klaebe netdev->ethtool_ops = &sxgbe_ethtool_ops; 5031edb9ca6SSiva Reddy } 504