1 /* Synopsys DesignWare Core Enterprise Ethernet (XLGMAC) Driver 2 * 3 * Copyright (c) 2017 Synopsys, Inc. (www.synopsys.com) 4 * 5 * This program is dual-licensed; you may select either version 2 of 6 * the GNU General Public License ("GPL") or BSD license ("BSD"). 7 * 8 * This Synopsys DWC XLGMAC software driver and associated documentation 9 * (hereinafter the "Software") is an unsupported proprietary work of 10 * Synopsys, Inc. unless otherwise expressly agreed to in writing between 11 * Synopsys and you. The Software IS NOT an item of Licensed Software or a 12 * Licensed Product under any End User Software License Agreement or 13 * Agreement for Licensed Products with Synopsys or any supplement thereto. 14 * Synopsys is a registered trademark of Synopsys, Inc. Other names included 15 * in the SOFTWARE may be the trademarks of their respective owners. 16 */ 17 18 #include <linux/ethtool.h> 19 #include <linux/kernel.h> 20 #include <linux/netdevice.h> 21 22 #include "dwc-xlgmac.h" 23 #include "dwc-xlgmac-reg.h" 24 25 struct xlgmac_stats_desc { 26 char stat_string[ETH_GSTRING_LEN]; 27 int stat_offset; 28 }; 29 30 #define XLGMAC_STAT(str, var) \ 31 { \ 32 str, \ 33 offsetof(struct xlgmac_pdata, stats.var), \ 34 } 35 36 static const struct xlgmac_stats_desc xlgmac_gstring_stats[] = { 37 /* MMC TX counters */ 38 XLGMAC_STAT("tx_bytes", txoctetcount_gb), 39 XLGMAC_STAT("tx_bytes_good", txoctetcount_g), 40 XLGMAC_STAT("tx_packets", txframecount_gb), 41 XLGMAC_STAT("tx_packets_good", txframecount_g), 42 XLGMAC_STAT("tx_unicast_packets", txunicastframes_gb), 43 XLGMAC_STAT("tx_broadcast_packets", txbroadcastframes_gb), 44 XLGMAC_STAT("tx_broadcast_packets_good", txbroadcastframes_g), 45 XLGMAC_STAT("tx_multicast_packets", txmulticastframes_gb), 46 XLGMAC_STAT("tx_multicast_packets_good", txmulticastframes_g), 47 XLGMAC_STAT("tx_vlan_packets_good", txvlanframes_g), 48 XLGMAC_STAT("tx_64_byte_packets", tx64octets_gb), 49 XLGMAC_STAT("tx_65_to_127_byte_packets", tx65to127octets_gb), 50 XLGMAC_STAT("tx_128_to_255_byte_packets", tx128to255octets_gb), 51 XLGMAC_STAT("tx_256_to_511_byte_packets", tx256to511octets_gb), 52 XLGMAC_STAT("tx_512_to_1023_byte_packets", tx512to1023octets_gb), 53 XLGMAC_STAT("tx_1024_to_max_byte_packets", tx1024tomaxoctets_gb), 54 XLGMAC_STAT("tx_underflow_errors", txunderflowerror), 55 XLGMAC_STAT("tx_pause_frames", txpauseframes), 56 57 /* MMC RX counters */ 58 XLGMAC_STAT("rx_bytes", rxoctetcount_gb), 59 XLGMAC_STAT("rx_bytes_good", rxoctetcount_g), 60 XLGMAC_STAT("rx_packets", rxframecount_gb), 61 XLGMAC_STAT("rx_unicast_packets_good", rxunicastframes_g), 62 XLGMAC_STAT("rx_broadcast_packets_good", rxbroadcastframes_g), 63 XLGMAC_STAT("rx_multicast_packets_good", rxmulticastframes_g), 64 XLGMAC_STAT("rx_vlan_packets", rxvlanframes_gb), 65 XLGMAC_STAT("rx_64_byte_packets", rx64octets_gb), 66 XLGMAC_STAT("rx_65_to_127_byte_packets", rx65to127octets_gb), 67 XLGMAC_STAT("rx_128_to_255_byte_packets", rx128to255octets_gb), 68 XLGMAC_STAT("rx_256_to_511_byte_packets", rx256to511octets_gb), 69 XLGMAC_STAT("rx_512_to_1023_byte_packets", rx512to1023octets_gb), 70 XLGMAC_STAT("rx_1024_to_max_byte_packets", rx1024tomaxoctets_gb), 71 XLGMAC_STAT("rx_undersize_packets_good", rxundersize_g), 72 XLGMAC_STAT("rx_oversize_packets_good", rxoversize_g), 73 XLGMAC_STAT("rx_crc_errors", rxcrcerror), 74 XLGMAC_STAT("rx_crc_errors_small_packets", rxrunterror), 75 XLGMAC_STAT("rx_crc_errors_giant_packets", rxjabbererror), 76 XLGMAC_STAT("rx_length_errors", rxlengtherror), 77 XLGMAC_STAT("rx_out_of_range_errors", rxoutofrangetype), 78 XLGMAC_STAT("rx_fifo_overflow_errors", rxfifooverflow), 79 XLGMAC_STAT("rx_watchdog_errors", rxwatchdogerror), 80 XLGMAC_STAT("rx_pause_frames", rxpauseframes), 81 82 /* Extra counters */ 83 XLGMAC_STAT("tx_tso_packets", tx_tso_packets), 84 XLGMAC_STAT("rx_split_header_packets", rx_split_header_packets), 85 XLGMAC_STAT("tx_process_stopped", tx_process_stopped), 86 XLGMAC_STAT("rx_process_stopped", rx_process_stopped), 87 XLGMAC_STAT("tx_buffer_unavailable", tx_buffer_unavailable), 88 XLGMAC_STAT("rx_buffer_unavailable", rx_buffer_unavailable), 89 XLGMAC_STAT("fatal_bus_error", fatal_bus_error), 90 XLGMAC_STAT("tx_vlan_packets", tx_vlan_packets), 91 XLGMAC_STAT("rx_vlan_packets", rx_vlan_packets), 92 XLGMAC_STAT("napi_poll_isr", napi_poll_isr), 93 XLGMAC_STAT("napi_poll_txtimer", napi_poll_txtimer), 94 }; 95 96 #define XLGMAC_STATS_COUNT ARRAY_SIZE(xlgmac_gstring_stats) 97 98 static void xlgmac_ethtool_get_drvinfo(struct net_device *netdev, 99 struct ethtool_drvinfo *drvinfo) 100 { 101 struct xlgmac_pdata *pdata = netdev_priv(netdev); 102 u32 ver = pdata->hw_feat.version; 103 u32 snpsver, devid, userver; 104 105 strlcpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver)); 106 strlcpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version)); 107 strlcpy(drvinfo->bus_info, dev_name(pdata->dev), 108 sizeof(drvinfo->bus_info)); 109 /* S|SNPSVER: Synopsys-defined Version 110 * D|DEVID: Indicates the Device family 111 * U|USERVER: User-defined Version 112 */ 113 snpsver = XLGMAC_GET_REG_BITS(ver, MAC_VR_SNPSVER_POS, 114 MAC_VR_SNPSVER_LEN); 115 devid = XLGMAC_GET_REG_BITS(ver, MAC_VR_DEVID_POS, 116 MAC_VR_DEVID_LEN); 117 userver = XLGMAC_GET_REG_BITS(ver, MAC_VR_USERVER_POS, 118 MAC_VR_USERVER_LEN); 119 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 120 "S.D.U: %x.%x.%x", snpsver, devid, userver); 121 } 122 123 static u32 xlgmac_ethtool_get_msglevel(struct net_device *netdev) 124 { 125 struct xlgmac_pdata *pdata = netdev_priv(netdev); 126 127 return pdata->msg_enable; 128 } 129 130 static void xlgmac_ethtool_set_msglevel(struct net_device *netdev, 131 u32 msglevel) 132 { 133 struct xlgmac_pdata *pdata = netdev_priv(netdev); 134 135 pdata->msg_enable = msglevel; 136 } 137 138 static void xlgmac_ethtool_get_channels(struct net_device *netdev, 139 struct ethtool_channels *channel) 140 { 141 struct xlgmac_pdata *pdata = netdev_priv(netdev); 142 143 channel->max_rx = XLGMAC_MAX_DMA_CHANNELS; 144 channel->max_tx = XLGMAC_MAX_DMA_CHANNELS; 145 channel->rx_count = pdata->rx_q_count; 146 channel->tx_count = pdata->tx_q_count; 147 } 148 149 static int xlgmac_ethtool_get_coalesce(struct net_device *netdev, 150 struct ethtool_coalesce *ec) 151 { 152 struct xlgmac_pdata *pdata = netdev_priv(netdev); 153 154 memset(ec, 0, sizeof(struct ethtool_coalesce)); 155 ec->rx_coalesce_usecs = pdata->rx_usecs; 156 ec->rx_max_coalesced_frames = pdata->rx_frames; 157 ec->tx_max_coalesced_frames = pdata->tx_frames; 158 159 return 0; 160 } 161 162 static int xlgmac_ethtool_set_coalesce(struct net_device *netdev, 163 struct ethtool_coalesce *ec) 164 { 165 struct xlgmac_pdata *pdata = netdev_priv(netdev); 166 struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops; 167 unsigned int rx_frames, rx_riwt, rx_usecs; 168 unsigned int tx_frames; 169 170 /* Check for not supported parameters */ 171 if ((ec->rx_coalesce_usecs_irq) || (ec->rx_max_coalesced_frames_irq) || 172 (ec->tx_coalesce_usecs) || (ec->tx_coalesce_usecs_high) || 173 (ec->tx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) || 174 (ec->stats_block_coalesce_usecs) || (ec->pkt_rate_low) || 175 (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) || 176 (ec->rx_max_coalesced_frames_low) || (ec->rx_coalesce_usecs_low) || 177 (ec->tx_coalesce_usecs_low) || (ec->tx_max_coalesced_frames_low) || 178 (ec->pkt_rate_high) || (ec->rx_coalesce_usecs_high) || 179 (ec->rx_max_coalesced_frames_high) || 180 (ec->tx_max_coalesced_frames_high) || 181 (ec->rate_sample_interval)) 182 return -EOPNOTSUPP; 183 184 rx_usecs = ec->rx_coalesce_usecs; 185 rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs); 186 rx_frames = ec->rx_max_coalesced_frames; 187 tx_frames = ec->tx_max_coalesced_frames; 188 189 if ((rx_riwt > XLGMAC_MAX_DMA_RIWT) || 190 (rx_riwt < XLGMAC_MIN_DMA_RIWT) || 191 (rx_frames > pdata->rx_desc_count)) 192 return -EINVAL; 193 194 if (tx_frames > pdata->tx_desc_count) 195 return -EINVAL; 196 197 pdata->rx_riwt = rx_riwt; 198 pdata->rx_usecs = rx_usecs; 199 pdata->rx_frames = rx_frames; 200 hw_ops->config_rx_coalesce(pdata); 201 202 pdata->tx_frames = tx_frames; 203 hw_ops->config_tx_coalesce(pdata); 204 205 return 0; 206 } 207 208 static void xlgmac_ethtool_get_strings(struct net_device *netdev, 209 u32 stringset, u8 *data) 210 { 211 int i; 212 213 switch (stringset) { 214 case ETH_SS_STATS: 215 for (i = 0; i < XLGMAC_STATS_COUNT; i++) { 216 memcpy(data, xlgmac_gstring_stats[i].stat_string, 217 ETH_GSTRING_LEN); 218 data += ETH_GSTRING_LEN; 219 } 220 break; 221 default: 222 WARN_ON(1); 223 break; 224 } 225 } 226 227 static int xlgmac_ethtool_get_sset_count(struct net_device *netdev, 228 int stringset) 229 { 230 int ret; 231 232 switch (stringset) { 233 case ETH_SS_STATS: 234 ret = XLGMAC_STATS_COUNT; 235 break; 236 237 default: 238 ret = -EOPNOTSUPP; 239 } 240 241 return ret; 242 } 243 244 static void xlgmac_ethtool_get_ethtool_stats(struct net_device *netdev, 245 struct ethtool_stats *stats, 246 u64 *data) 247 { 248 struct xlgmac_pdata *pdata = netdev_priv(netdev); 249 u8 *stat; 250 int i; 251 252 pdata->hw_ops.read_mmc_stats(pdata); 253 for (i = 0; i < XLGMAC_STATS_COUNT; i++) { 254 stat = (u8 *)pdata + xlgmac_gstring_stats[i].stat_offset; 255 *data++ = *(u64 *)stat; 256 } 257 } 258 259 static const struct ethtool_ops xlgmac_ethtool_ops = { 260 .get_drvinfo = xlgmac_ethtool_get_drvinfo, 261 .get_link = ethtool_op_get_link, 262 .get_msglevel = xlgmac_ethtool_get_msglevel, 263 .set_msglevel = xlgmac_ethtool_set_msglevel, 264 .get_channels = xlgmac_ethtool_get_channels, 265 .get_coalesce = xlgmac_ethtool_get_coalesce, 266 .set_coalesce = xlgmac_ethtool_set_coalesce, 267 .get_strings = xlgmac_ethtool_get_strings, 268 .get_sset_count = xlgmac_ethtool_get_sset_count, 269 .get_ethtool_stats = xlgmac_ethtool_get_ethtool_stats, 270 }; 271 272 const struct ethtool_ops *xlgmac_get_ethtool_ops(void) 273 { 274 return &xlgmac_ethtool_ops; 275 } 276