1 /** 2 * Copyright 2013 Cisco Systems, Inc. All rights reserved. 3 * 4 * This program is free software; you may redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; version 2 of the License. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 15 * SOFTWARE. 16 * 17 */ 18 19 #include <linux/netdevice.h> 20 #include <linux/ethtool.h> 21 22 #include "enic_res.h" 23 #include "enic.h" 24 #include "enic_dev.h" 25 #include "enic_clsf.h" 26 27 struct enic_stat { 28 char name[ETH_GSTRING_LEN]; 29 unsigned int index; 30 }; 31 32 #define ENIC_TX_STAT(stat) { \ 33 .name = #stat, \ 34 .index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \ 35 } 36 37 #define ENIC_RX_STAT(stat) { \ 38 .name = #stat, \ 39 .index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \ 40 } 41 42 static const struct enic_stat enic_tx_stats[] = { 43 ENIC_TX_STAT(tx_frames_ok), 44 ENIC_TX_STAT(tx_unicast_frames_ok), 45 ENIC_TX_STAT(tx_multicast_frames_ok), 46 ENIC_TX_STAT(tx_broadcast_frames_ok), 47 ENIC_TX_STAT(tx_bytes_ok), 48 ENIC_TX_STAT(tx_unicast_bytes_ok), 49 ENIC_TX_STAT(tx_multicast_bytes_ok), 50 ENIC_TX_STAT(tx_broadcast_bytes_ok), 51 ENIC_TX_STAT(tx_drops), 52 ENIC_TX_STAT(tx_errors), 53 ENIC_TX_STAT(tx_tso), 54 }; 55 56 static const struct enic_stat enic_rx_stats[] = { 57 ENIC_RX_STAT(rx_frames_ok), 58 ENIC_RX_STAT(rx_frames_total), 59 ENIC_RX_STAT(rx_unicast_frames_ok), 60 ENIC_RX_STAT(rx_multicast_frames_ok), 61 ENIC_RX_STAT(rx_broadcast_frames_ok), 62 ENIC_RX_STAT(rx_bytes_ok), 63 ENIC_RX_STAT(rx_unicast_bytes_ok), 64 ENIC_RX_STAT(rx_multicast_bytes_ok), 65 ENIC_RX_STAT(rx_broadcast_bytes_ok), 66 ENIC_RX_STAT(rx_drop), 67 ENIC_RX_STAT(rx_no_bufs), 68 ENIC_RX_STAT(rx_errors), 69 ENIC_RX_STAT(rx_rss), 70 ENIC_RX_STAT(rx_crc_errors), 71 ENIC_RX_STAT(rx_frames_64), 72 ENIC_RX_STAT(rx_frames_127), 73 ENIC_RX_STAT(rx_frames_255), 74 ENIC_RX_STAT(rx_frames_511), 75 ENIC_RX_STAT(rx_frames_1023), 76 ENIC_RX_STAT(rx_frames_1518), 77 ENIC_RX_STAT(rx_frames_to_max), 78 }; 79 80 static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats); 81 static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats); 82 83 void enic_intr_coal_set_rx(struct enic *enic, u32 timer) 84 { 85 int i; 86 int intr; 87 88 for (i = 0; i < enic->rq_count; i++) { 89 intr = enic_msix_rq_intr(enic, i); 90 vnic_intr_coalescing_timer_set(&enic->intr[intr], timer); 91 } 92 } 93 94 static int enic_get_settings(struct net_device *netdev, 95 struct ethtool_cmd *ecmd) 96 { 97 struct enic *enic = netdev_priv(netdev); 98 99 ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); 100 ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); 101 ecmd->port = PORT_FIBRE; 102 ecmd->transceiver = XCVR_EXTERNAL; 103 104 if (netif_carrier_ok(netdev)) { 105 ethtool_cmd_speed_set(ecmd, vnic_dev_port_speed(enic->vdev)); 106 ecmd->duplex = DUPLEX_FULL; 107 } else { 108 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); 109 ecmd->duplex = DUPLEX_UNKNOWN; 110 } 111 112 ecmd->autoneg = AUTONEG_DISABLE; 113 114 return 0; 115 } 116 117 static void enic_get_drvinfo(struct net_device *netdev, 118 struct ethtool_drvinfo *drvinfo) 119 { 120 struct enic *enic = netdev_priv(netdev); 121 struct vnic_devcmd_fw_info *fw_info; 122 123 enic_dev_fw_info(enic, &fw_info); 124 125 strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); 126 strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); 127 strlcpy(drvinfo->fw_version, fw_info->fw_version, 128 sizeof(drvinfo->fw_version)); 129 strlcpy(drvinfo->bus_info, pci_name(enic->pdev), 130 sizeof(drvinfo->bus_info)); 131 } 132 133 static void enic_get_strings(struct net_device *netdev, u32 stringset, 134 u8 *data) 135 { 136 unsigned int i; 137 138 switch (stringset) { 139 case ETH_SS_STATS: 140 for (i = 0; i < enic_n_tx_stats; i++) { 141 memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN); 142 data += ETH_GSTRING_LEN; 143 } 144 for (i = 0; i < enic_n_rx_stats; i++) { 145 memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN); 146 data += ETH_GSTRING_LEN; 147 } 148 break; 149 } 150 } 151 152 static int enic_get_sset_count(struct net_device *netdev, int sset) 153 { 154 switch (sset) { 155 case ETH_SS_STATS: 156 return enic_n_tx_stats + enic_n_rx_stats; 157 default: 158 return -EOPNOTSUPP; 159 } 160 } 161 162 static void enic_get_ethtool_stats(struct net_device *netdev, 163 struct ethtool_stats *stats, u64 *data) 164 { 165 struct enic *enic = netdev_priv(netdev); 166 struct vnic_stats *vstats; 167 unsigned int i; 168 169 enic_dev_stats_dump(enic, &vstats); 170 171 for (i = 0; i < enic_n_tx_stats; i++) 172 *(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].index]; 173 for (i = 0; i < enic_n_rx_stats; i++) 174 *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].index]; 175 } 176 177 static u32 enic_get_msglevel(struct net_device *netdev) 178 { 179 struct enic *enic = netdev_priv(netdev); 180 return enic->msg_enable; 181 } 182 183 static void enic_set_msglevel(struct net_device *netdev, u32 value) 184 { 185 struct enic *enic = netdev_priv(netdev); 186 enic->msg_enable = value; 187 } 188 189 static int enic_get_coalesce(struct net_device *netdev, 190 struct ethtool_coalesce *ecmd) 191 { 192 struct enic *enic = netdev_priv(netdev); 193 struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting; 194 195 ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs; 196 ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs; 197 if (rxcoal->use_adaptive_rx_coalesce) 198 ecmd->use_adaptive_rx_coalesce = 1; 199 ecmd->rx_coalesce_usecs_low = rxcoal->small_pkt_range_start; 200 ecmd->rx_coalesce_usecs_high = rxcoal->range_end; 201 202 return 0; 203 } 204 205 static int enic_set_coalesce(struct net_device *netdev, 206 struct ethtool_coalesce *ecmd) 207 { 208 struct enic *enic = netdev_priv(netdev); 209 u32 tx_coalesce_usecs; 210 u32 rx_coalesce_usecs; 211 u32 rx_coalesce_usecs_low; 212 u32 rx_coalesce_usecs_high; 213 u32 coalesce_usecs_max; 214 unsigned int i, intr; 215 struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting; 216 217 coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev); 218 tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, 219 coalesce_usecs_max); 220 rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, 221 coalesce_usecs_max); 222 223 rx_coalesce_usecs_low = min_t(u32, ecmd->rx_coalesce_usecs_low, 224 coalesce_usecs_max); 225 rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high, 226 coalesce_usecs_max); 227 228 switch (vnic_dev_get_intr_mode(enic->vdev)) { 229 case VNIC_DEV_INTR_MODE_INTX: 230 if (tx_coalesce_usecs != rx_coalesce_usecs) 231 return -EINVAL; 232 if (ecmd->use_adaptive_rx_coalesce || 233 ecmd->rx_coalesce_usecs_low || 234 ecmd->rx_coalesce_usecs_high) 235 return -EINVAL; 236 237 intr = enic_legacy_io_intr(); 238 vnic_intr_coalescing_timer_set(&enic->intr[intr], 239 tx_coalesce_usecs); 240 break; 241 case VNIC_DEV_INTR_MODE_MSI: 242 if (tx_coalesce_usecs != rx_coalesce_usecs) 243 return -EINVAL; 244 if (ecmd->use_adaptive_rx_coalesce || 245 ecmd->rx_coalesce_usecs_low || 246 ecmd->rx_coalesce_usecs_high) 247 return -EINVAL; 248 249 vnic_intr_coalescing_timer_set(&enic->intr[0], 250 tx_coalesce_usecs); 251 break; 252 case VNIC_DEV_INTR_MODE_MSIX: 253 if (ecmd->rx_coalesce_usecs_high && 254 (rx_coalesce_usecs_high < 255 rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF)) 256 return -EINVAL; 257 258 for (i = 0; i < enic->wq_count; i++) { 259 intr = enic_msix_wq_intr(enic, i); 260 vnic_intr_coalescing_timer_set(&enic->intr[intr], 261 tx_coalesce_usecs); 262 } 263 264 rxcoal->use_adaptive_rx_coalesce = 265 !!ecmd->use_adaptive_rx_coalesce; 266 if (!rxcoal->use_adaptive_rx_coalesce) 267 enic_intr_coal_set_rx(enic, rx_coalesce_usecs); 268 269 if (ecmd->rx_coalesce_usecs_high) { 270 rxcoal->range_end = rx_coalesce_usecs_high; 271 rxcoal->small_pkt_range_start = rx_coalesce_usecs_low; 272 rxcoal->large_pkt_range_start = rx_coalesce_usecs_low + 273 ENIC_AIC_LARGE_PKT_DIFF; 274 } 275 break; 276 default: 277 break; 278 } 279 280 enic->tx_coalesce_usecs = tx_coalesce_usecs; 281 enic->rx_coalesce_usecs = rx_coalesce_usecs; 282 283 return 0; 284 } 285 286 static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd, 287 u32 *rule_locs) 288 { 289 int j, ret = 0, cnt = 0; 290 291 cmd->data = enic->rfs_h.max - enic->rfs_h.free; 292 for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) { 293 struct hlist_head *hhead; 294 struct hlist_node *tmp; 295 struct enic_rfs_fltr_node *n; 296 297 hhead = &enic->rfs_h.ht_head[j]; 298 hlist_for_each_entry_safe(n, tmp, hhead, node) { 299 if (cnt == cmd->rule_cnt) 300 return -EMSGSIZE; 301 rule_locs[cnt] = n->fltr_id; 302 cnt++; 303 } 304 } 305 cmd->rule_cnt = cnt; 306 307 return ret; 308 } 309 310 static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd) 311 { 312 struct ethtool_rx_flow_spec *fsp = 313 (struct ethtool_rx_flow_spec *)&cmd->fs; 314 struct enic_rfs_fltr_node *n; 315 316 n = htbl_fltr_search(enic, (u16)fsp->location); 317 if (!n) 318 return -EINVAL; 319 switch (n->keys.ip_proto) { 320 case IPPROTO_TCP: 321 fsp->flow_type = TCP_V4_FLOW; 322 break; 323 case IPPROTO_UDP: 324 fsp->flow_type = UDP_V4_FLOW; 325 break; 326 default: 327 return -EINVAL; 328 break; 329 } 330 331 fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src; 332 fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0; 333 334 fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst; 335 fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0; 336 337 fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0]; 338 fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0; 339 340 fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1]; 341 fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0; 342 343 fsp->ring_cookie = n->rq_id; 344 345 return 0; 346 } 347 348 static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, 349 u32 *rule_locs) 350 { 351 struct enic *enic = netdev_priv(dev); 352 int ret = 0; 353 354 switch (cmd->cmd) { 355 case ETHTOOL_GRXRINGS: 356 cmd->data = enic->rq_count; 357 break; 358 case ETHTOOL_GRXCLSRLCNT: 359 spin_lock_bh(&enic->rfs_h.lock); 360 cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free; 361 cmd->data = enic->rfs_h.max; 362 spin_unlock_bh(&enic->rfs_h.lock); 363 break; 364 case ETHTOOL_GRXCLSRLALL: 365 spin_lock_bh(&enic->rfs_h.lock); 366 ret = enic_grxclsrlall(enic, cmd, rule_locs); 367 spin_unlock_bh(&enic->rfs_h.lock); 368 break; 369 case ETHTOOL_GRXCLSRULE: 370 spin_lock_bh(&enic->rfs_h.lock); 371 ret = enic_grxclsrule(enic, cmd); 372 spin_unlock_bh(&enic->rfs_h.lock); 373 break; 374 default: 375 ret = -EOPNOTSUPP; 376 break; 377 } 378 379 return ret; 380 } 381 382 static int enic_get_tunable(struct net_device *dev, 383 const struct ethtool_tunable *tuna, void *data) 384 { 385 struct enic *enic = netdev_priv(dev); 386 int ret = 0; 387 388 switch (tuna->id) { 389 case ETHTOOL_RX_COPYBREAK: 390 *(u32 *)data = enic->rx_copybreak; 391 break; 392 default: 393 ret = -EINVAL; 394 break; 395 } 396 397 return ret; 398 } 399 400 static int enic_set_tunable(struct net_device *dev, 401 const struct ethtool_tunable *tuna, 402 const void *data) 403 { 404 struct enic *enic = netdev_priv(dev); 405 int ret = 0; 406 407 switch (tuna->id) { 408 case ETHTOOL_RX_COPYBREAK: 409 enic->rx_copybreak = *(u32 *)data; 410 break; 411 default: 412 ret = -EINVAL; 413 break; 414 } 415 416 return ret; 417 } 418 419 static const struct ethtool_ops enic_ethtool_ops = { 420 .get_settings = enic_get_settings, 421 .get_drvinfo = enic_get_drvinfo, 422 .get_msglevel = enic_get_msglevel, 423 .set_msglevel = enic_set_msglevel, 424 .get_link = ethtool_op_get_link, 425 .get_strings = enic_get_strings, 426 .get_sset_count = enic_get_sset_count, 427 .get_ethtool_stats = enic_get_ethtool_stats, 428 .get_coalesce = enic_get_coalesce, 429 .set_coalesce = enic_set_coalesce, 430 .get_rxnfc = enic_get_rxnfc, 431 .get_tunable = enic_get_tunable, 432 .set_tunable = enic_set_tunable, 433 }; 434 435 void enic_set_ethtool_ops(struct net_device *netdev) 436 { 437 netdev->ethtool_ops = &enic_ethtool_ops; 438 } 439