1 /* 2 * Copyright (C) 2015 Cavium, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License 6 * as published by the Free Software Foundation. 7 */ 8 9 /* ETHTOOL Support for VNIC_VF Device*/ 10 11 #include <linux/pci.h> 12 13 #include "nic_reg.h" 14 #include "nic.h" 15 #include "nicvf_queues.h" 16 #include "q_struct.h" 17 #include "thunder_bgx.h" 18 19 #define DRV_NAME "thunder-nicvf" 20 #define DRV_VERSION "1.0" 21 22 struct nicvf_stat { 23 char name[ETH_GSTRING_LEN]; 24 unsigned int index; 25 }; 26 27 #define NICVF_HW_STAT(stat) { \ 28 .name = #stat, \ 29 .index = offsetof(struct nicvf_hw_stats, stat) / sizeof(u64), \ 30 } 31 32 #define NICVF_DRV_STAT(stat) { \ 33 .name = #stat, \ 34 .index = offsetof(struct nicvf_drv_stats, stat) / sizeof(u64), \ 35 } 36 37 static const struct nicvf_stat nicvf_hw_stats[] = { 38 NICVF_HW_STAT(rx_bytes), 39 NICVF_HW_STAT(rx_ucast_frames), 40 NICVF_HW_STAT(rx_bcast_frames), 41 NICVF_HW_STAT(rx_mcast_frames), 42 NICVF_HW_STAT(rx_fcs_errors), 43 NICVF_HW_STAT(rx_l2_errors), 44 NICVF_HW_STAT(rx_drop_red), 45 NICVF_HW_STAT(rx_drop_red_bytes), 46 NICVF_HW_STAT(rx_drop_overrun), 47 NICVF_HW_STAT(rx_drop_overrun_bytes), 48 NICVF_HW_STAT(rx_drop_bcast), 49 NICVF_HW_STAT(rx_drop_mcast), 50 NICVF_HW_STAT(rx_drop_l3_bcast), 51 NICVF_HW_STAT(rx_drop_l3_mcast), 52 NICVF_HW_STAT(rx_bgx_truncated_pkts), 53 NICVF_HW_STAT(rx_jabber_errs), 54 NICVF_HW_STAT(rx_fcs_errs), 55 NICVF_HW_STAT(rx_bgx_errs), 56 NICVF_HW_STAT(rx_prel2_errs), 57 NICVF_HW_STAT(rx_l2_hdr_malformed), 58 NICVF_HW_STAT(rx_oversize), 59 NICVF_HW_STAT(rx_undersize), 60 NICVF_HW_STAT(rx_l2_len_mismatch), 61 NICVF_HW_STAT(rx_l2_pclp), 62 NICVF_HW_STAT(rx_ip_ver_errs), 63 NICVF_HW_STAT(rx_ip_csum_errs), 64 NICVF_HW_STAT(rx_ip_hdr_malformed), 65 NICVF_HW_STAT(rx_ip_payload_malformed), 66 NICVF_HW_STAT(rx_ip_ttl_errs), 67 NICVF_HW_STAT(rx_l3_pclp), 68 NICVF_HW_STAT(rx_l4_malformed), 69 NICVF_HW_STAT(rx_l4_csum_errs), 70 NICVF_HW_STAT(rx_udp_len_errs), 71 NICVF_HW_STAT(rx_l4_port_errs), 72 NICVF_HW_STAT(rx_tcp_flag_errs), 73 NICVF_HW_STAT(rx_tcp_offset_errs), 74 NICVF_HW_STAT(rx_l4_pclp), 75 NICVF_HW_STAT(rx_truncated_pkts), 76 NICVF_HW_STAT(tx_bytes_ok), 77 NICVF_HW_STAT(tx_ucast_frames_ok), 78 NICVF_HW_STAT(tx_bcast_frames_ok), 79 NICVF_HW_STAT(tx_mcast_frames_ok), 80 }; 81 82 static const struct nicvf_stat nicvf_drv_stats[] = { 83 NICVF_DRV_STAT(rx_frames_ok), 84 NICVF_DRV_STAT(rx_frames_64), 85 NICVF_DRV_STAT(rx_frames_127), 86 NICVF_DRV_STAT(rx_frames_255), 87 NICVF_DRV_STAT(rx_frames_511), 88 NICVF_DRV_STAT(rx_frames_1023), 89 NICVF_DRV_STAT(rx_frames_1518), 90 NICVF_DRV_STAT(rx_frames_jumbo), 91 NICVF_DRV_STAT(rx_drops), 92 NICVF_DRV_STAT(rcv_buffer_alloc_failures), 93 NICVF_DRV_STAT(tx_frames_ok), 94 NICVF_DRV_STAT(tx_tso), 95 NICVF_DRV_STAT(tx_drops), 96 NICVF_DRV_STAT(tx_timeout), 97 NICVF_DRV_STAT(txq_stop), 98 NICVF_DRV_STAT(txq_wake), 99 }; 100 101 static const struct nicvf_stat nicvf_queue_stats[] = { 102 { "bytes", 0 }, 103 { "frames", 1 }, 104 }; 105 106 static const unsigned int nicvf_n_hw_stats = ARRAY_SIZE(nicvf_hw_stats); 107 static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats); 108 static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats); 109 110 static int nicvf_get_settings(struct net_device *netdev, 111 struct ethtool_cmd *cmd) 112 { 113 struct nicvf *nic = netdev_priv(netdev); 114 115 cmd->supported = 0; 116 cmd->transceiver = XCVR_EXTERNAL; 117 118 if (!nic->link_up) { 119 cmd->duplex = DUPLEX_UNKNOWN; 120 ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); 121 return 0; 122 } 123 124 if (nic->speed <= 1000) { 125 cmd->port = PORT_MII; 126 cmd->autoneg = AUTONEG_ENABLE; 127 } else { 128 cmd->port = PORT_FIBRE; 129 cmd->autoneg = AUTONEG_DISABLE; 130 } 131 cmd->duplex = nic->duplex; 132 ethtool_cmd_speed_set(cmd, nic->speed); 133 134 return 0; 135 } 136 137 static u32 nicvf_get_link(struct net_device *netdev) 138 { 139 struct nicvf *nic = netdev_priv(netdev); 140 141 return nic->link_up; 142 } 143 144 static void nicvf_get_drvinfo(struct net_device *netdev, 145 struct ethtool_drvinfo *info) 146 { 147 struct nicvf *nic = netdev_priv(netdev); 148 149 strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 150 strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 151 strlcpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info)); 152 } 153 154 static u32 nicvf_get_msglevel(struct net_device *netdev) 155 { 156 struct nicvf *nic = netdev_priv(netdev); 157 158 return nic->msg_enable; 159 } 160 161 static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl) 162 { 163 struct nicvf *nic = netdev_priv(netdev); 164 165 nic->msg_enable = lvl; 166 } 167 168 static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset) 169 { 170 int stats, qidx; 171 int start_qidx = qset * MAX_RCV_QUEUES_PER_QS; 172 173 for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) { 174 for (stats = 0; stats < nicvf_n_queue_stats; stats++) { 175 sprintf(*data, "rxq%d: %s", qidx + start_qidx, 176 nicvf_queue_stats[stats].name); 177 *data += ETH_GSTRING_LEN; 178 } 179 } 180 181 for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) { 182 for (stats = 0; stats < nicvf_n_queue_stats; stats++) { 183 sprintf(*data, "txq%d: %s", qidx + start_qidx, 184 nicvf_queue_stats[stats].name); 185 *data += ETH_GSTRING_LEN; 186 } 187 } 188 } 189 190 static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) 191 { 192 struct nicvf *nic = netdev_priv(netdev); 193 int stats; 194 int sqs; 195 196 if (sset != ETH_SS_STATS) 197 return; 198 199 for (stats = 0; stats < nicvf_n_hw_stats; stats++) { 200 memcpy(data, nicvf_hw_stats[stats].name, ETH_GSTRING_LEN); 201 data += ETH_GSTRING_LEN; 202 } 203 204 for (stats = 0; stats < nicvf_n_drv_stats; stats++) { 205 memcpy(data, nicvf_drv_stats[stats].name, ETH_GSTRING_LEN); 206 data += ETH_GSTRING_LEN; 207 } 208 209 nicvf_get_qset_strings(nic, &data, 0); 210 211 for (sqs = 0; sqs < nic->sqs_count; sqs++) { 212 if (!nic->snicvf[sqs]) 213 continue; 214 nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1); 215 } 216 217 for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) { 218 sprintf(data, "bgx_rxstat%d: ", stats); 219 data += ETH_GSTRING_LEN; 220 } 221 222 for (stats = 0; stats < BGX_TX_STATS_COUNT; stats++) { 223 sprintf(data, "bgx_txstat%d: ", stats); 224 data += ETH_GSTRING_LEN; 225 } 226 } 227 228 static int nicvf_get_sset_count(struct net_device *netdev, int sset) 229 { 230 struct nicvf *nic = netdev_priv(netdev); 231 int qstats_count; 232 int sqs; 233 234 if (sset != ETH_SS_STATS) 235 return -EINVAL; 236 237 qstats_count = nicvf_n_queue_stats * 238 (nic->qs->rq_cnt + nic->qs->sq_cnt); 239 for (sqs = 0; sqs < nic->sqs_count; sqs++) { 240 struct nicvf *snic; 241 242 snic = nic->snicvf[sqs]; 243 if (!snic) 244 continue; 245 qstats_count += nicvf_n_queue_stats * 246 (snic->qs->rq_cnt + snic->qs->sq_cnt); 247 } 248 249 return nicvf_n_hw_stats + nicvf_n_drv_stats + 250 qstats_count + 251 BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT; 252 } 253 254 static void nicvf_get_qset_stats(struct nicvf *nic, 255 struct ethtool_stats *stats, u64 **data) 256 { 257 int stat, qidx; 258 259 if (!nic) 260 return; 261 262 for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) { 263 nicvf_update_rq_stats(nic, qidx); 264 for (stat = 0; stat < nicvf_n_queue_stats; stat++) 265 *((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats) 266 [nicvf_queue_stats[stat].index]; 267 } 268 269 for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) { 270 nicvf_update_sq_stats(nic, qidx); 271 for (stat = 0; stat < nicvf_n_queue_stats; stat++) 272 *((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats) 273 [nicvf_queue_stats[stat].index]; 274 } 275 } 276 277 static void nicvf_get_ethtool_stats(struct net_device *netdev, 278 struct ethtool_stats *stats, u64 *data) 279 { 280 struct nicvf *nic = netdev_priv(netdev); 281 int stat; 282 int sqs; 283 284 nicvf_update_stats(nic); 285 286 /* Update LMAC stats */ 287 nicvf_update_lmac_stats(nic); 288 289 for (stat = 0; stat < nicvf_n_hw_stats; stat++) 290 *(data++) = ((u64 *)&nic->hw_stats) 291 [nicvf_hw_stats[stat].index]; 292 for (stat = 0; stat < nicvf_n_drv_stats; stat++) 293 *(data++) = ((u64 *)&nic->drv_stats) 294 [nicvf_drv_stats[stat].index]; 295 296 nicvf_get_qset_stats(nic, stats, &data); 297 298 for (sqs = 0; sqs < nic->sqs_count; sqs++) { 299 if (!nic->snicvf[sqs]) 300 continue; 301 nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data); 302 } 303 304 for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++) 305 *(data++) = nic->bgx_stats.rx_stats[stat]; 306 for (stat = 0; stat < BGX_TX_STATS_COUNT; stat++) 307 *(data++) = nic->bgx_stats.tx_stats[stat]; 308 } 309 310 static int nicvf_get_regs_len(struct net_device *dev) 311 { 312 return sizeof(u64) * NIC_VF_REG_COUNT; 313 } 314 315 static void nicvf_get_regs(struct net_device *dev, 316 struct ethtool_regs *regs, void *reg) 317 { 318 struct nicvf *nic = netdev_priv(dev); 319 u64 *p = (u64 *)reg; 320 u64 reg_offset; 321 int mbox, key, stat, q; 322 int i = 0; 323 324 regs->version = 0; 325 memset(p, 0, NIC_VF_REG_COUNT); 326 327 p[i++] = nicvf_reg_read(nic, NIC_VNIC_CFG); 328 /* Mailbox registers */ 329 for (mbox = 0; mbox < NIC_PF_VF_MAILBOX_SIZE; mbox++) 330 p[i++] = nicvf_reg_read(nic, 331 NIC_VF_PF_MAILBOX_0_1 | (mbox << 3)); 332 333 p[i++] = nicvf_reg_read(nic, NIC_VF_INT); 334 p[i++] = nicvf_reg_read(nic, NIC_VF_INT_W1S); 335 p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1C); 336 p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1S); 337 p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG); 338 339 for (key = 0; key < RSS_HASH_KEY_SIZE; key++) 340 p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_KEY_0_4 | (key << 3)); 341 342 /* Tx/Rx statistics */ 343 for (stat = 0; stat < TX_STATS_ENUM_LAST; stat++) 344 p[i++] = nicvf_reg_read(nic, 345 NIC_VNIC_TX_STAT_0_4 | (stat << 3)); 346 347 for (i = 0; i < RX_STATS_ENUM_LAST; i++) 348 p[i++] = nicvf_reg_read(nic, 349 NIC_VNIC_RX_STAT_0_13 | (stat << 3)); 350 351 p[i++] = nicvf_reg_read(nic, NIC_QSET_RQ_GEN_CFG); 352 353 /* All completion queue's registers */ 354 for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++) { 355 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG, q); 356 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG2, q); 357 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_THRESH, q); 358 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_BASE, q); 359 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, q); 360 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, q); 361 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DOOR, q); 362 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS, q); 363 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS2, q); 364 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DEBUG, q); 365 } 366 367 /* All receive queue's registers */ 368 for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++) { 369 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_CFG, q); 370 p[i++] = nicvf_queue_reg_read(nic, 371 NIC_QSET_RQ_0_7_STAT_0_1, q); 372 reg_offset = NIC_QSET_RQ_0_7_STAT_0_1 | (1 << 3); 373 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); 374 } 375 376 for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++) { 377 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, q); 378 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_THRESH, q); 379 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_BASE, q); 380 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, q); 381 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, q); 382 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q); 383 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q); 384 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q); 385 /* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which 386 * produces bus errors when read 387 */ 388 p[i++] = 0; 389 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q); 390 reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3); 391 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); 392 } 393 394 for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++) { 395 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_CFG, q); 396 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_THRESH, q); 397 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_BASE, q); 398 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, q); 399 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, q); 400 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_DOOR, q); 401 p[i++] = nicvf_queue_reg_read(nic, 402 NIC_QSET_RBDR_0_1_STATUS0, q); 403 p[i++] = nicvf_queue_reg_read(nic, 404 NIC_QSET_RBDR_0_1_STATUS1, q); 405 reg_offset = NIC_QSET_RBDR_0_1_PREFETCH_STATUS; 406 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); 407 } 408 } 409 410 static int nicvf_get_coalesce(struct net_device *netdev, 411 struct ethtool_coalesce *cmd) 412 { 413 struct nicvf *nic = netdev_priv(netdev); 414 415 cmd->rx_coalesce_usecs = nic->cq_coalesce_usecs; 416 return 0; 417 } 418 419 static void nicvf_get_ringparam(struct net_device *netdev, 420 struct ethtool_ringparam *ring) 421 { 422 struct nicvf *nic = netdev_priv(netdev); 423 struct queue_set *qs = nic->qs; 424 425 ring->rx_max_pending = MAX_RCV_BUF_COUNT; 426 ring->rx_pending = qs->rbdr_len; 427 ring->tx_max_pending = MAX_SND_QUEUE_LEN; 428 ring->tx_pending = qs->sq_len; 429 } 430 431 static int nicvf_get_rss_hash_opts(struct nicvf *nic, 432 struct ethtool_rxnfc *info) 433 { 434 info->data = 0; 435 436 switch (info->flow_type) { 437 case TCP_V4_FLOW: 438 case TCP_V6_FLOW: 439 case UDP_V4_FLOW: 440 case UDP_V6_FLOW: 441 case SCTP_V4_FLOW: 442 case SCTP_V6_FLOW: 443 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; 444 case IPV4_FLOW: 445 case IPV6_FLOW: 446 info->data |= RXH_IP_SRC | RXH_IP_DST; 447 break; 448 default: 449 return -EINVAL; 450 } 451 452 return 0; 453 } 454 455 static int nicvf_get_rxnfc(struct net_device *dev, 456 struct ethtool_rxnfc *info, u32 *rules) 457 { 458 struct nicvf *nic = netdev_priv(dev); 459 int ret = -EOPNOTSUPP; 460 461 switch (info->cmd) { 462 case ETHTOOL_GRXRINGS: 463 info->data = nic->rx_queues; 464 ret = 0; 465 break; 466 case ETHTOOL_GRXFH: 467 return nicvf_get_rss_hash_opts(nic, info); 468 default: 469 break; 470 } 471 return ret; 472 } 473 474 static int nicvf_set_rss_hash_opts(struct nicvf *nic, 475 struct ethtool_rxnfc *info) 476 { 477 struct nicvf_rss_info *rss = &nic->rss_info; 478 u64 rss_cfg = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG); 479 480 if (!rss->enable) 481 netdev_err(nic->netdev, 482 "RSS is disabled, hash cannot be set\n"); 483 484 netdev_info(nic->netdev, "Set RSS flow type = %d, data = %lld\n", 485 info->flow_type, info->data); 486 487 if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST)) 488 return -EINVAL; 489 490 switch (info->flow_type) { 491 case TCP_V4_FLOW: 492 case TCP_V6_FLOW: 493 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 494 case 0: 495 rss_cfg &= ~(1ULL << RSS_HASH_TCP); 496 break; 497 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 498 rss_cfg |= (1ULL << RSS_HASH_TCP); 499 break; 500 default: 501 return -EINVAL; 502 } 503 break; 504 case UDP_V4_FLOW: 505 case UDP_V6_FLOW: 506 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 507 case 0: 508 rss_cfg &= ~(1ULL << RSS_HASH_UDP); 509 break; 510 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 511 rss_cfg |= (1ULL << RSS_HASH_UDP); 512 break; 513 default: 514 return -EINVAL; 515 } 516 break; 517 case SCTP_V4_FLOW: 518 case SCTP_V6_FLOW: 519 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { 520 case 0: 521 rss_cfg &= ~(1ULL << RSS_HASH_L4ETC); 522 break; 523 case (RXH_L4_B_0_1 | RXH_L4_B_2_3): 524 rss_cfg |= (1ULL << RSS_HASH_L4ETC); 525 break; 526 default: 527 return -EINVAL; 528 } 529 break; 530 case IPV4_FLOW: 531 case IPV6_FLOW: 532 rss_cfg = RSS_HASH_IP; 533 break; 534 default: 535 return -EINVAL; 536 } 537 538 nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss_cfg); 539 return 0; 540 } 541 542 static int nicvf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) 543 { 544 struct nicvf *nic = netdev_priv(dev); 545 546 switch (info->cmd) { 547 case ETHTOOL_SRXFH: 548 return nicvf_set_rss_hash_opts(nic, info); 549 default: 550 break; 551 } 552 return -EOPNOTSUPP; 553 } 554 555 static u32 nicvf_get_rxfh_key_size(struct net_device *netdev) 556 { 557 return RSS_HASH_KEY_SIZE * sizeof(u64); 558 } 559 560 static u32 nicvf_get_rxfh_indir_size(struct net_device *dev) 561 { 562 struct nicvf *nic = netdev_priv(dev); 563 564 return nic->rss_info.rss_size; 565 } 566 567 static int nicvf_get_rxfh(struct net_device *dev, u32 *indir, u8 *hkey, 568 u8 *hfunc) 569 { 570 struct nicvf *nic = netdev_priv(dev); 571 struct nicvf_rss_info *rss = &nic->rss_info; 572 int idx; 573 574 if (indir) { 575 for (idx = 0; idx < rss->rss_size; idx++) 576 indir[idx] = rss->ind_tbl[idx]; 577 } 578 579 if (hkey) 580 memcpy(hkey, rss->key, RSS_HASH_KEY_SIZE * sizeof(u64)); 581 582 if (hfunc) 583 *hfunc = ETH_RSS_HASH_TOP; 584 585 return 0; 586 } 587 588 static int nicvf_set_rxfh(struct net_device *dev, const u32 *indir, 589 const u8 *hkey, u8 hfunc) 590 { 591 struct nicvf *nic = netdev_priv(dev); 592 struct nicvf_rss_info *rss = &nic->rss_info; 593 int idx; 594 595 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 596 return -EOPNOTSUPP; 597 598 if (!rss->enable) { 599 netdev_err(nic->netdev, 600 "RSS is disabled, cannot change settings\n"); 601 return -EIO; 602 } 603 604 if (indir) { 605 for (idx = 0; idx < rss->rss_size; idx++) 606 rss->ind_tbl[idx] = indir[idx]; 607 } 608 609 if (hkey) { 610 memcpy(rss->key, hkey, RSS_HASH_KEY_SIZE * sizeof(u64)); 611 nicvf_set_rss_key(nic); 612 } 613 614 nicvf_config_rss(nic); 615 return 0; 616 } 617 618 /* Get no of queues device supports and current queue count */ 619 static void nicvf_get_channels(struct net_device *dev, 620 struct ethtool_channels *channel) 621 { 622 struct nicvf *nic = netdev_priv(dev); 623 624 memset(channel, 0, sizeof(*channel)); 625 626 channel->max_rx = nic->max_queues; 627 channel->max_tx = nic->max_queues; 628 629 channel->rx_count = nic->rx_queues; 630 channel->tx_count = nic->tx_queues; 631 } 632 633 /* Set no of Tx, Rx queues to be used */ 634 static int nicvf_set_channels(struct net_device *dev, 635 struct ethtool_channels *channel) 636 { 637 struct nicvf *nic = netdev_priv(dev); 638 int err = 0; 639 bool if_up = netif_running(dev); 640 int cqcount; 641 642 if (!channel->rx_count || !channel->tx_count) 643 return -EINVAL; 644 if (channel->rx_count > nic->max_queues) 645 return -EINVAL; 646 if (channel->tx_count > nic->max_queues) 647 return -EINVAL; 648 649 if (if_up) 650 nicvf_stop(dev); 651 652 cqcount = max(channel->rx_count, channel->tx_count); 653 654 if (cqcount > MAX_CMP_QUEUES_PER_QS) { 655 nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS); 656 nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1; 657 } else { 658 nic->sqs_count = 0; 659 } 660 661 nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS); 662 nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS); 663 nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt); 664 665 nic->rx_queues = channel->rx_count; 666 nic->tx_queues = channel->tx_count; 667 err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues); 668 if (err) 669 return err; 670 671 if (if_up) 672 nicvf_open(dev); 673 674 netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n", 675 nic->tx_queues, nic->rx_queues); 676 677 return err; 678 } 679 680 static const struct ethtool_ops nicvf_ethtool_ops = { 681 .get_settings = nicvf_get_settings, 682 .get_link = nicvf_get_link, 683 .get_drvinfo = nicvf_get_drvinfo, 684 .get_msglevel = nicvf_get_msglevel, 685 .set_msglevel = nicvf_set_msglevel, 686 .get_strings = nicvf_get_strings, 687 .get_sset_count = nicvf_get_sset_count, 688 .get_ethtool_stats = nicvf_get_ethtool_stats, 689 .get_regs_len = nicvf_get_regs_len, 690 .get_regs = nicvf_get_regs, 691 .get_coalesce = nicvf_get_coalesce, 692 .get_ringparam = nicvf_get_ringparam, 693 .get_rxnfc = nicvf_get_rxnfc, 694 .set_rxnfc = nicvf_set_rxnfc, 695 .get_rxfh_key_size = nicvf_get_rxfh_key_size, 696 .get_rxfh_indir_size = nicvf_get_rxfh_indir_size, 697 .get_rxfh = nicvf_get_rxfh, 698 .set_rxfh = nicvf_set_rxfh, 699 .get_channels = nicvf_get_channels, 700 .set_channels = nicvf_set_channels, 701 .get_ts_info = ethtool_op_get_ts_info, 702 }; 703 704 void nicvf_set_ethtool_ops(struct net_device *netdev) 705 { 706 netdev->ethtool_ops = &nicvf_ethtool_ops; 707 } 708