0001
0002
0003
0004 #include "tsnep.h"
0005
0006 static const char tsnep_stats_strings[][ETH_GSTRING_LEN] = {
0007 "rx_packets",
0008 "rx_bytes",
0009 "rx_dropped",
0010 "rx_multicast",
0011 "rx_phy_errors",
0012 "rx_forwarded_phy_errors",
0013 "rx_invalid_frame_errors",
0014 "tx_packets",
0015 "tx_bytes",
0016 "tx_dropped",
0017 };
0018
0019 struct tsnep_stats {
0020 u64 rx_packets;
0021 u64 rx_bytes;
0022 u64 rx_dropped;
0023 u64 rx_multicast;
0024 u64 rx_phy_errors;
0025 u64 rx_forwarded_phy_errors;
0026 u64 rx_invalid_frame_errors;
0027 u64 tx_packets;
0028 u64 tx_bytes;
0029 u64 tx_dropped;
0030 };
0031
0032 #define TSNEP_STATS_COUNT (sizeof(struct tsnep_stats) / sizeof(u64))
0033
0034 static const char tsnep_rx_queue_stats_strings[][ETH_GSTRING_LEN] = {
0035 "rx_%d_packets",
0036 "rx_%d_bytes",
0037 "rx_%d_dropped",
0038 "rx_%d_multicast",
0039 "rx_%d_no_descriptor_errors",
0040 "rx_%d_buffer_too_small_errors",
0041 "rx_%d_fifo_overflow_errors",
0042 "rx_%d_invalid_frame_errors",
0043 };
0044
0045 struct tsnep_rx_queue_stats {
0046 u64 rx_packets;
0047 u64 rx_bytes;
0048 u64 rx_dropped;
0049 u64 rx_multicast;
0050 u64 rx_no_descriptor_errors;
0051 u64 rx_buffer_too_small_errors;
0052 u64 rx_fifo_overflow_errors;
0053 u64 rx_invalid_frame_errors;
0054 };
0055
0056 #define TSNEP_RX_QUEUE_STATS_COUNT (sizeof(struct tsnep_rx_queue_stats) / \
0057 sizeof(u64))
0058
0059 static const char tsnep_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
0060 "tx_%d_packets",
0061 "tx_%d_bytes",
0062 "tx_%d_dropped",
0063 };
0064
0065 struct tsnep_tx_queue_stats {
0066 u64 tx_packets;
0067 u64 tx_bytes;
0068 u64 tx_dropped;
0069 };
0070
0071 #define TSNEP_TX_QUEUE_STATS_COUNT (sizeof(struct tsnep_tx_queue_stats) / \
0072 sizeof(u64))
0073
0074 static void tsnep_ethtool_get_drvinfo(struct net_device *netdev,
0075 struct ethtool_drvinfo *drvinfo)
0076 {
0077 struct tsnep_adapter *adapter = netdev_priv(netdev);
0078
0079 strscpy(drvinfo->driver, TSNEP, sizeof(drvinfo->driver));
0080 strscpy(drvinfo->bus_info, dev_name(&adapter->pdev->dev),
0081 sizeof(drvinfo->bus_info));
0082 }
0083
0084 static int tsnep_ethtool_get_regs_len(struct net_device *netdev)
0085 {
0086 struct tsnep_adapter *adapter = netdev_priv(netdev);
0087 int len;
0088 int num_additional_queues;
0089
0090 len = TSNEP_MAC_SIZE;
0091
0092
0093
0094
0095 num_additional_queues =
0096 max(adapter->num_tx_queues, adapter->num_rx_queues) - 1;
0097 len += TSNEP_QUEUE_SIZE * num_additional_queues;
0098
0099 return len;
0100 }
0101
0102 static void tsnep_ethtool_get_regs(struct net_device *netdev,
0103 struct ethtool_regs *regs,
0104 void *p)
0105 {
0106 struct tsnep_adapter *adapter = netdev_priv(netdev);
0107
0108 regs->version = 1;
0109
0110 memcpy_fromio(p, adapter->addr, regs->len);
0111 }
0112
0113 static u32 tsnep_ethtool_get_msglevel(struct net_device *netdev)
0114 {
0115 struct tsnep_adapter *adapter = netdev_priv(netdev);
0116
0117 return adapter->msg_enable;
0118 }
0119
0120 static void tsnep_ethtool_set_msglevel(struct net_device *netdev, u32 data)
0121 {
0122 struct tsnep_adapter *adapter = netdev_priv(netdev);
0123
0124 adapter->msg_enable = data;
0125 }
0126
0127 static void tsnep_ethtool_get_strings(struct net_device *netdev, u32 stringset,
0128 u8 *data)
0129 {
0130 struct tsnep_adapter *adapter = netdev_priv(netdev);
0131 int rx_count = adapter->num_rx_queues;
0132 int tx_count = adapter->num_tx_queues;
0133 int i, j;
0134
0135 switch (stringset) {
0136 case ETH_SS_STATS:
0137 memcpy(data, tsnep_stats_strings, sizeof(tsnep_stats_strings));
0138 data += sizeof(tsnep_stats_strings);
0139
0140 for (i = 0; i < rx_count; i++) {
0141 for (j = 0; j < TSNEP_RX_QUEUE_STATS_COUNT; j++) {
0142 snprintf(data, ETH_GSTRING_LEN,
0143 tsnep_rx_queue_stats_strings[j], i);
0144 data += ETH_GSTRING_LEN;
0145 }
0146 }
0147
0148 for (i = 0; i < tx_count; i++) {
0149 for (j = 0; j < TSNEP_TX_QUEUE_STATS_COUNT; j++) {
0150 snprintf(data, ETH_GSTRING_LEN,
0151 tsnep_tx_queue_stats_strings[j], i);
0152 data += ETH_GSTRING_LEN;
0153 }
0154 }
0155 break;
0156 case ETH_SS_TEST:
0157 tsnep_ethtool_get_test_strings(data);
0158 break;
0159 }
0160 }
0161
0162 static void tsnep_ethtool_get_ethtool_stats(struct net_device *netdev,
0163 struct ethtool_stats *stats,
0164 u64 *data)
0165 {
0166 struct tsnep_adapter *adapter = netdev_priv(netdev);
0167 int rx_count = adapter->num_rx_queues;
0168 int tx_count = adapter->num_tx_queues;
0169 struct tsnep_stats tsnep_stats;
0170 struct tsnep_rx_queue_stats tsnep_rx_queue_stats;
0171 struct tsnep_tx_queue_stats tsnep_tx_queue_stats;
0172 u32 reg;
0173 int i;
0174
0175 memset(&tsnep_stats, 0, sizeof(tsnep_stats));
0176 for (i = 0; i < adapter->num_rx_queues; i++) {
0177 tsnep_stats.rx_packets += adapter->rx[i].packets;
0178 tsnep_stats.rx_bytes += adapter->rx[i].bytes;
0179 tsnep_stats.rx_dropped += adapter->rx[i].dropped;
0180 tsnep_stats.rx_multicast += adapter->rx[i].multicast;
0181 }
0182 reg = ioread32(adapter->addr + ECM_STAT);
0183 tsnep_stats.rx_phy_errors =
0184 (reg & ECM_STAT_RX_ERR_MASK) >> ECM_STAT_RX_ERR_SHIFT;
0185 tsnep_stats.rx_forwarded_phy_errors =
0186 (reg & ECM_STAT_FWD_RX_ERR_MASK) >> ECM_STAT_FWD_RX_ERR_SHIFT;
0187 tsnep_stats.rx_invalid_frame_errors =
0188 (reg & ECM_STAT_INV_FRM_MASK) >> ECM_STAT_INV_FRM_SHIFT;
0189 for (i = 0; i < adapter->num_tx_queues; i++) {
0190 tsnep_stats.tx_packets += adapter->tx[i].packets;
0191 tsnep_stats.tx_bytes += adapter->tx[i].bytes;
0192 tsnep_stats.tx_dropped += adapter->tx[i].dropped;
0193 }
0194 memcpy(data, &tsnep_stats, sizeof(tsnep_stats));
0195 data += TSNEP_STATS_COUNT;
0196
0197 for (i = 0; i < rx_count; i++) {
0198 memset(&tsnep_rx_queue_stats, 0, sizeof(tsnep_rx_queue_stats));
0199 tsnep_rx_queue_stats.rx_packets = adapter->rx[i].packets;
0200 tsnep_rx_queue_stats.rx_bytes = adapter->rx[i].bytes;
0201 tsnep_rx_queue_stats.rx_dropped = adapter->rx[i].dropped;
0202 tsnep_rx_queue_stats.rx_multicast = adapter->rx[i].multicast;
0203 reg = ioread32(adapter->addr + TSNEP_QUEUE(i) +
0204 TSNEP_RX_STATISTIC);
0205 tsnep_rx_queue_stats.rx_no_descriptor_errors =
0206 (reg & TSNEP_RX_STATISTIC_NO_DESC_MASK) >>
0207 TSNEP_RX_STATISTIC_NO_DESC_SHIFT;
0208 tsnep_rx_queue_stats.rx_buffer_too_small_errors =
0209 (reg & TSNEP_RX_STATISTIC_BUFFER_TOO_SMALL_MASK) >>
0210 TSNEP_RX_STATISTIC_BUFFER_TOO_SMALL_SHIFT;
0211 tsnep_rx_queue_stats.rx_fifo_overflow_errors =
0212 (reg & TSNEP_RX_STATISTIC_FIFO_OVERFLOW_MASK) >>
0213 TSNEP_RX_STATISTIC_FIFO_OVERFLOW_SHIFT;
0214 tsnep_rx_queue_stats.rx_invalid_frame_errors =
0215 (reg & TSNEP_RX_STATISTIC_INVALID_FRAME_MASK) >>
0216 TSNEP_RX_STATISTIC_INVALID_FRAME_SHIFT;
0217 memcpy(data, &tsnep_rx_queue_stats,
0218 sizeof(tsnep_rx_queue_stats));
0219 data += TSNEP_RX_QUEUE_STATS_COUNT;
0220 }
0221
0222 for (i = 0; i < tx_count; i++) {
0223 memset(&tsnep_tx_queue_stats, 0, sizeof(tsnep_tx_queue_stats));
0224 tsnep_tx_queue_stats.tx_packets += adapter->tx[i].packets;
0225 tsnep_tx_queue_stats.tx_bytes += adapter->tx[i].bytes;
0226 tsnep_tx_queue_stats.tx_dropped += adapter->tx[i].dropped;
0227 memcpy(data, &tsnep_tx_queue_stats,
0228 sizeof(tsnep_tx_queue_stats));
0229 data += TSNEP_TX_QUEUE_STATS_COUNT;
0230 }
0231 }
0232
0233 static int tsnep_ethtool_get_sset_count(struct net_device *netdev, int sset)
0234 {
0235 struct tsnep_adapter *adapter = netdev_priv(netdev);
0236 int rx_count;
0237 int tx_count;
0238
0239 switch (sset) {
0240 case ETH_SS_STATS:
0241 rx_count = adapter->num_rx_queues;
0242 tx_count = adapter->num_tx_queues;
0243 return TSNEP_STATS_COUNT +
0244 TSNEP_RX_QUEUE_STATS_COUNT * rx_count +
0245 TSNEP_TX_QUEUE_STATS_COUNT * tx_count;
0246 case ETH_SS_TEST:
0247 return tsnep_ethtool_get_test_count();
0248 default:
0249 return -EOPNOTSUPP;
0250 }
0251 }
0252
0253 static int tsnep_ethtool_get_ts_info(struct net_device *dev,
0254 struct ethtool_ts_info *info)
0255 {
0256 struct tsnep_adapter *adapter = netdev_priv(dev);
0257
0258 info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
0259 SOF_TIMESTAMPING_RX_SOFTWARE |
0260 SOF_TIMESTAMPING_SOFTWARE |
0261 SOF_TIMESTAMPING_TX_HARDWARE |
0262 SOF_TIMESTAMPING_RX_HARDWARE |
0263 SOF_TIMESTAMPING_RAW_HARDWARE;
0264
0265 if (adapter->ptp_clock)
0266 info->phc_index = ptp_clock_index(adapter->ptp_clock);
0267 else
0268 info->phc_index = -1;
0269
0270 info->tx_types = BIT(HWTSTAMP_TX_OFF) |
0271 BIT(HWTSTAMP_TX_ON);
0272 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
0273 BIT(HWTSTAMP_FILTER_ALL);
0274
0275 return 0;
0276 }
0277
0278 const struct ethtool_ops tsnep_ethtool_ops = {
0279 .get_drvinfo = tsnep_ethtool_get_drvinfo,
0280 .get_regs_len = tsnep_ethtool_get_regs_len,
0281 .get_regs = tsnep_ethtool_get_regs,
0282 .get_msglevel = tsnep_ethtool_get_msglevel,
0283 .set_msglevel = tsnep_ethtool_set_msglevel,
0284 .nway_reset = phy_ethtool_nway_reset,
0285 .get_link = ethtool_op_get_link,
0286 .self_test = tsnep_ethtool_self_test,
0287 .get_strings = tsnep_ethtool_get_strings,
0288 .get_ethtool_stats = tsnep_ethtool_get_ethtool_stats,
0289 .get_sset_count = tsnep_ethtool_get_sset_count,
0290 .get_ts_info = tsnep_ethtool_get_ts_info,
0291 .get_link_ksettings = phy_ethtool_get_link_ksettings,
0292 .set_link_ksettings = phy_ethtool_set_link_ksettings,
0293 };