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 ec->rx_coalesce_usecs = pdata->rx_usecs; 155 ec->rx_max_coalesced_frames = pdata->rx_frames; 156 ec->tx_max_coalesced_frames = pdata->tx_frames; 157 158 return 0; 159 } 160 161 static int xlgmac_ethtool_set_coalesce(struct net_device *netdev, 162 struct ethtool_coalesce *ec) 163 { 164 struct xlgmac_pdata *pdata = netdev_priv(netdev); 165 struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops; 166 unsigned int rx_frames, rx_riwt, rx_usecs; 167 unsigned int tx_frames; 168 169 rx_usecs = ec->rx_coalesce_usecs; 170 rx_riwt = hw_ops->usec_to_riwt(pdata, rx_usecs); 171 rx_frames = ec->rx_max_coalesced_frames; 172 tx_frames = ec->tx_max_coalesced_frames; 173 174 if ((rx_riwt > XLGMAC_MAX_DMA_RIWT) || 175 (rx_riwt < XLGMAC_MIN_DMA_RIWT) || 176 (rx_frames > pdata->rx_desc_count)) 177 return -EINVAL; 178 179 if (tx_frames > pdata->tx_desc_count) 180 return -EINVAL; 181 182 pdata->rx_riwt = rx_riwt; 183 pdata->rx_usecs = rx_usecs; 184 pdata->rx_frames = rx_frames; 185 hw_ops->config_rx_coalesce(pdata); 186 187 pdata->tx_frames = tx_frames; 188 hw_ops->config_tx_coalesce(pdata); 189 190 return 0; 191 } 192 193 static void xlgmac_ethtool_get_strings(struct net_device *netdev, 194 u32 stringset, u8 *data) 195 { 196 int i; 197 198 switch (stringset) { 199 case ETH_SS_STATS: 200 for (i = 0; i < XLGMAC_STATS_COUNT; i++) { 201 memcpy(data, xlgmac_gstring_stats[i].stat_string, 202 ETH_GSTRING_LEN); 203 data += ETH_GSTRING_LEN; 204 } 205 break; 206 default: 207 WARN_ON(1); 208 break; 209 } 210 } 211 212 static int xlgmac_ethtool_get_sset_count(struct net_device *netdev, 213 int stringset) 214 { 215 int ret; 216 217 switch (stringset) { 218 case ETH_SS_STATS: 219 ret = XLGMAC_STATS_COUNT; 220 break; 221 222 default: 223 ret = -EOPNOTSUPP; 224 } 225 226 return ret; 227 } 228 229 static void xlgmac_ethtool_get_ethtool_stats(struct net_device *netdev, 230 struct ethtool_stats *stats, 231 u64 *data) 232 { 233 struct xlgmac_pdata *pdata = netdev_priv(netdev); 234 u8 *stat; 235 int i; 236 237 pdata->hw_ops.read_mmc_stats(pdata); 238 for (i = 0; i < XLGMAC_STATS_COUNT; i++) { 239 stat = (u8 *)pdata + xlgmac_gstring_stats[i].stat_offset; 240 *data++ = *(u64 *)stat; 241 } 242 } 243 244 static const struct ethtool_ops xlgmac_ethtool_ops = { 245 .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | 246 ETHTOOL_COALESCE_MAX_FRAMES, 247 .get_drvinfo = xlgmac_ethtool_get_drvinfo, 248 .get_link = ethtool_op_get_link, 249 .get_msglevel = xlgmac_ethtool_get_msglevel, 250 .set_msglevel = xlgmac_ethtool_set_msglevel, 251 .get_channels = xlgmac_ethtool_get_channels, 252 .get_coalesce = xlgmac_ethtool_get_coalesce, 253 .set_coalesce = xlgmac_ethtool_set_coalesce, 254 .get_strings = xlgmac_ethtool_get_strings, 255 .get_sset_count = xlgmac_ethtool_get_sset_count, 256 .get_ethtool_stats = xlgmac_ethtool_get_ethtool_stats, 257 }; 258 259 const struct ethtool_ops *xlgmac_get_ethtool_ops(void) 260 { 261 return &xlgmac_ethtool_ops; 262 } 263