1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell Octeon EP (EndPoint) VF Ethernet Driver 3 * 4 * Copyright (C) 2020 Marvell. 5 * 6 */ 7 8 #include <linux/pci.h> 9 #include <linux/netdevice.h> 10 #include <linux/ethtool.h> 11 12 #include "octep_vf_config.h" 13 #include "octep_vf_main.h" 14 15 static const char octep_vf_gstrings_global_stats[][ETH_GSTRING_LEN] = { 16 "rx_alloc_errors", 17 "tx_busy_errors", 18 "tx_hw_pkts", 19 "tx_hw_octs", 20 "tx_hw_bcast", 21 "tx_hw_mcast", 22 "rx_hw_pkts", 23 "rx_hw_bytes", 24 "rx_hw_bcast", 25 "rx_dropped_bytes_fifo_full", 26 }; 27 28 #define OCTEP_VF_GLOBAL_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_global_stats) 29 30 static const char octep_vf_gstrings_tx_q_stats[][ETH_GSTRING_LEN] = { 31 "tx_packets_posted[Q-%u]", 32 "tx_packets_completed[Q-%u]", 33 "tx_bytes[Q-%u]", 34 "tx_busy[Q-%u]", 35 }; 36 37 #define OCTEP_VF_TX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_tx_q_stats) 38 39 static const char octep_vf_gstrings_rx_q_stats[][ETH_GSTRING_LEN] = { 40 "rx_packets[Q-%u]", 41 "rx_bytes[Q-%u]", 42 "rx_alloc_errors[Q-%u]", 43 }; 44 45 #define OCTEP_VF_RX_Q_STATS_CNT ARRAY_SIZE(octep_vf_gstrings_rx_q_stats) 46 47 static void octep_vf_get_drvinfo(struct net_device *netdev, 48 struct ethtool_drvinfo *info) 49 { 50 struct octep_vf_device *oct = netdev_priv(netdev); 51 52 strscpy(info->driver, OCTEP_VF_DRV_NAME, sizeof(info->driver)); 53 strscpy(info->bus_info, pci_name(oct->pdev), sizeof(info->bus_info)); 54 } 55 56 static void octep_vf_get_strings(struct net_device *netdev, 57 u32 stringset, u8 *data) 58 { 59 struct octep_vf_device *oct = netdev_priv(netdev); 60 u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); 61 const char *str; 62 int i, j; 63 64 switch (stringset) { 65 case ETH_SS_STATS: 66 for (i = 0; i < OCTEP_VF_GLOBAL_STATS_CNT; i++) 67 ethtool_puts(&data, octep_vf_gstrings_global_stats[i]); 68 69 for (i = 0; i < num_queues; i++) 70 for (j = 0; j < OCTEP_VF_TX_Q_STATS_CNT; j++) { 71 str = octep_vf_gstrings_tx_q_stats[j]; 72 ethtool_sprintf(&data, str, i); 73 } 74 75 for (i = 0; i < num_queues; i++) 76 for (j = 0; j < OCTEP_VF_RX_Q_STATS_CNT; j++) { 77 str = octep_vf_gstrings_rx_q_stats[j]; 78 ethtool_sprintf(&data, str, i); 79 } 80 break; 81 default: 82 break; 83 } 84 } 85 86 static int octep_vf_get_sset_count(struct net_device *netdev, int sset) 87 { 88 struct octep_vf_device *oct = netdev_priv(netdev); 89 u16 num_queues = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); 90 91 switch (sset) { 92 case ETH_SS_STATS: 93 return OCTEP_VF_GLOBAL_STATS_CNT + (num_queues * 94 (OCTEP_VF_TX_Q_STATS_CNT + OCTEP_VF_RX_Q_STATS_CNT)); 95 break; 96 default: 97 return -EOPNOTSUPP; 98 } 99 } 100 101 static void octep_vf_get_ethtool_stats(struct net_device *netdev, 102 struct ethtool_stats *stats, u64 *data) 103 { 104 struct octep_vf_device *oct = netdev_priv(netdev); 105 struct octep_vf_iface_tx_stats *iface_tx_stats; 106 struct octep_vf_iface_rx_stats *iface_rx_stats; 107 u64 rx_alloc_errors, tx_busy_errors; 108 int q, i; 109 110 rx_alloc_errors = 0; 111 tx_busy_errors = 0; 112 113 octep_vf_get_if_stats(oct); 114 iface_tx_stats = &oct->iface_tx_stats; 115 iface_rx_stats = &oct->iface_rx_stats; 116 117 for (q = 0; q < OCTEP_VF_MAX_QUEUES; q++) { 118 tx_busy_errors += oct->stats_iq[q].tx_busy; 119 rx_alloc_errors += oct->stats_oq[q].alloc_failures; 120 } 121 i = 0; 122 data[i++] = rx_alloc_errors; 123 data[i++] = tx_busy_errors; 124 data[i++] = iface_tx_stats->pkts; 125 data[i++] = iface_tx_stats->octs; 126 data[i++] = iface_tx_stats->bcst; 127 data[i++] = iface_tx_stats->mcst; 128 data[i++] = iface_rx_stats->pkts; 129 data[i++] = iface_rx_stats->octets; 130 data[i++] = iface_rx_stats->bcast_pkts; 131 data[i++] = iface_rx_stats->dropped_octets_fifo_full; 132 133 /* Per Tx Queue stats */ 134 for (q = 0; q < OCTEP_VF_MAX_QUEUES; q++) { 135 data[i++] = oct->stats_iq[q].instr_posted; 136 data[i++] = oct->stats_iq[q].instr_completed; 137 data[i++] = oct->stats_iq[q].bytes_sent; 138 data[i++] = oct->stats_iq[q].tx_busy; 139 } 140 141 /* Per Rx Queue stats */ 142 for (q = 0; q < oct->num_oqs; q++) { 143 data[i++] = oct->stats_oq[q].packets; 144 data[i++] = oct->stats_oq[q].bytes; 145 data[i++] = oct->stats_oq[q].alloc_failures; 146 } 147 } 148 149 #define OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(octep_vf_speeds, ksettings, name) \ 150 { \ 151 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_T)) \ 152 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseT_Full); \ 153 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_R)) \ 154 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseR_FEC); \ 155 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_CR)) \ 156 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseCR_Full); \ 157 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_KR)) \ 158 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseKR_Full); \ 159 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_LR)) \ 160 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseLR_Full); \ 161 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_10GBASE_SR)) \ 162 ethtool_link_ksettings_add_link_mode(ksettings, name, 10000baseSR_Full); \ 163 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_CR)) \ 164 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseCR_Full); \ 165 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_KR)) \ 166 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseKR_Full); \ 167 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_25GBASE_SR)) \ 168 ethtool_link_ksettings_add_link_mode(ksettings, name, 25000baseSR_Full); \ 169 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_CR4)) \ 170 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseCR4_Full); \ 171 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_KR4)) \ 172 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseKR4_Full); \ 173 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_LR4)) \ 174 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseLR4_Full); \ 175 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_40GBASE_SR4)) \ 176 ethtool_link_ksettings_add_link_mode(ksettings, name, 40000baseSR4_Full); \ 177 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR2)) \ 178 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR2_Full); \ 179 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR2)) \ 180 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR2_Full); \ 181 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR2)) \ 182 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR2_Full); \ 183 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_CR)) \ 184 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseCR_Full); \ 185 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_KR)) \ 186 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseKR_Full); \ 187 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_LR)) \ 188 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseLR_ER_FR_Full); \ 189 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_50GBASE_SR)) \ 190 ethtool_link_ksettings_add_link_mode(ksettings, name, 50000baseSR_Full); \ 191 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_CR4)) \ 192 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseCR4_Full); \ 193 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_KR4)) \ 194 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseKR4_Full); \ 195 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_LR4)) \ 196 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseLR4_ER4_Full); \ 197 if ((octep_vf_speeds) & BIT(OCTEP_VF_LINK_MODE_100GBASE_SR4)) \ 198 ethtool_link_ksettings_add_link_mode(ksettings, name, 100000baseSR4_Full); \ 199 } 200 201 static int octep_vf_get_link_ksettings(struct net_device *netdev, 202 struct ethtool_link_ksettings *cmd) 203 { 204 struct octep_vf_device *oct = netdev_priv(netdev); 205 struct octep_vf_iface_link_info *link_info; 206 u32 advertised_modes, supported_modes; 207 208 ethtool_link_ksettings_zero_link_mode(cmd, supported); 209 ethtool_link_ksettings_zero_link_mode(cmd, advertising); 210 211 octep_vf_get_link_info(oct); 212 213 advertised_modes = oct->link_info.advertised_modes; 214 supported_modes = oct->link_info.supported_modes; 215 link_info = &oct->link_info; 216 217 OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(supported_modes, cmd, supported); 218 OCTEP_VF_SET_ETHTOOL_LINK_MODES_BITMAP(advertised_modes, cmd, advertising); 219 220 if (link_info->autoneg) { 221 if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_SUPPORTED) 222 ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); 223 if (link_info->autoneg & OCTEP_VF_LINK_MODE_AUTONEG_ADVERTISED) { 224 ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); 225 cmd->base.autoneg = AUTONEG_ENABLE; 226 } else { 227 cmd->base.autoneg = AUTONEG_DISABLE; 228 } 229 } else { 230 cmd->base.autoneg = AUTONEG_DISABLE; 231 } 232 233 cmd->base.port = PORT_FIBRE; 234 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 235 ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); 236 237 if (netif_carrier_ok(netdev)) { 238 cmd->base.speed = link_info->speed; 239 cmd->base.duplex = DUPLEX_FULL; 240 } else { 241 cmd->base.speed = SPEED_UNKNOWN; 242 cmd->base.duplex = DUPLEX_UNKNOWN; 243 } 244 return 0; 245 } 246 247 static const struct ethtool_ops octep_vf_ethtool_ops = { 248 .get_drvinfo = octep_vf_get_drvinfo, 249 .get_link = ethtool_op_get_link, 250 .get_strings = octep_vf_get_strings, 251 .get_sset_count = octep_vf_get_sset_count, 252 .get_ethtool_stats = octep_vf_get_ethtool_stats, 253 .get_link_ksettings = octep_vf_get_link_ksettings, 254 }; 255 256 void octep_vf_set_ethtool_ops(struct net_device *netdev) 257 { 258 netdev->ethtool_ops = &octep_vf_ethtool_ops; 259 } 260