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