aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h14
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c181
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c13
3 files changed, 197 insertions, 11 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 796db53954d9..b23a6678acc9 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -386,12 +386,14 @@ struct igb_adapter {
386 char fw_version[32]; 386 char fw_version[32];
387}; 387};
388 388
389#define IGB_FLAG_HAS_MSI (1 << 0) 389#define IGB_FLAG_HAS_MSI (1 << 0)
390#define IGB_FLAG_DCA_ENABLED (1 << 1) 390#define IGB_FLAG_DCA_ENABLED (1 << 1)
391#define IGB_FLAG_QUAD_PORT_A (1 << 2) 391#define IGB_FLAG_QUAD_PORT_A (1 << 2)
392#define IGB_FLAG_QUEUE_PAIRS (1 << 3) 392#define IGB_FLAG_QUEUE_PAIRS (1 << 3)
393#define IGB_FLAG_DMAC (1 << 4) 393#define IGB_FLAG_DMAC (1 << 4)
394#define IGB_FLAG_PTP (1 << 5) 394#define IGB_FLAG_PTP (1 << 5)
395#define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 6)
396#define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 7)
395 397
396/* DMA Coalescing defines */ 398/* DMA Coalescing defines */
397#define IGB_MIN_TXPBSIZE 20408 399#define IGB_MIN_TXPBSIZE 20408
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index d8b1bee606c0..2b82a53f4ab3 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2350,6 +2350,185 @@ static int igb_get_ts_info(struct net_device *dev,
2350 } 2350 }
2351} 2351}
2352 2352
2353static int igb_get_rss_hash_opts(struct igb_adapter *adapter,
2354 struct ethtool_rxnfc *cmd)
2355{
2356 cmd->data = 0;
2357
2358 /* Report default options for RSS on igb */
2359 switch (cmd->flow_type) {
2360 case TCP_V4_FLOW:
2361 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2362 case UDP_V4_FLOW:
2363 if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
2364 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2365 case SCTP_V4_FLOW:
2366 case AH_ESP_V4_FLOW:
2367 case AH_V4_FLOW:
2368 case ESP_V4_FLOW:
2369 case IPV4_FLOW:
2370 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
2371 break;
2372 case TCP_V6_FLOW:
2373 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2374 case UDP_V6_FLOW:
2375 if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
2376 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2377 case SCTP_V6_FLOW:
2378 case AH_ESP_V6_FLOW:
2379 case AH_V6_FLOW:
2380 case ESP_V6_FLOW:
2381 case IPV6_FLOW:
2382 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
2383 break;
2384 default:
2385 return -EINVAL;
2386 }
2387
2388 return 0;
2389}
2390
2391static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
2392 u32 *rule_locs)
2393{
2394 struct igb_adapter *adapter = netdev_priv(dev);
2395 int ret = -EOPNOTSUPP;
2396
2397 switch (cmd->cmd) {
2398 case ETHTOOL_GRXRINGS:
2399 cmd->data = adapter->num_rx_queues;
2400 ret = 0;
2401 break;
2402 case ETHTOOL_GRXFH:
2403 ret = igb_get_rss_hash_opts(adapter, cmd);
2404 break;
2405 default:
2406 break;
2407 }
2408
2409 return ret;
2410}
2411
2412#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \
2413 IGB_FLAG_RSS_FIELD_IPV6_UDP)
2414static int igb_set_rss_hash_opt(struct igb_adapter *adapter,
2415 struct ethtool_rxnfc *nfc)
2416{
2417 u32 flags = adapter->flags;
2418
2419 /* RSS does not support anything other than hashing
2420 * to queues on src and dst IPs and ports
2421 */
2422 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
2423 RXH_L4_B_0_1 | RXH_L4_B_2_3))
2424 return -EINVAL;
2425
2426 switch (nfc->flow_type) {
2427 case TCP_V4_FLOW:
2428 case TCP_V6_FLOW:
2429 if (!(nfc->data & RXH_IP_SRC) ||
2430 !(nfc->data & RXH_IP_DST) ||
2431 !(nfc->data & RXH_L4_B_0_1) ||
2432 !(nfc->data & RXH_L4_B_2_3))
2433 return -EINVAL;
2434 break;
2435 case UDP_V4_FLOW:
2436 if (!(nfc->data & RXH_IP_SRC) ||
2437 !(nfc->data & RXH_IP_DST))
2438 return -EINVAL;
2439 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
2440 case 0:
2441 flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP;
2442 break;
2443 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
2444 flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP;
2445 break;
2446 default:
2447 return -EINVAL;
2448 }
2449 break;
2450 case UDP_V6_FLOW:
2451 if (!(nfc->data & RXH_IP_SRC) ||
2452 !(nfc->data & RXH_IP_DST))
2453 return -EINVAL;
2454 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
2455 case 0:
2456 flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP;
2457 break;
2458 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
2459 flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP;
2460 break;
2461 default:
2462 return -EINVAL;
2463 }
2464 break;
2465 case AH_ESP_V4_FLOW:
2466 case AH_V4_FLOW:
2467 case ESP_V4_FLOW:
2468 case SCTP_V4_FLOW:
2469 case AH_ESP_V6_FLOW:
2470 case AH_V6_FLOW:
2471 case ESP_V6_FLOW:
2472 case SCTP_V6_FLOW:
2473 if (!(nfc->data & RXH_IP_SRC) ||
2474 !(nfc->data & RXH_IP_DST) ||
2475 (nfc->data & RXH_L4_B_0_1) ||
2476 (nfc->data & RXH_L4_B_2_3))
2477 return -EINVAL;
2478 break;
2479 default:
2480 return -EINVAL;
2481 }
2482
2483 /* if we changed something we need to update flags */
2484 if (flags != adapter->flags) {
2485 struct e1000_hw *hw = &adapter->hw;
2486 u32 mrqc = rd32(E1000_MRQC);
2487
2488 if ((flags & UDP_RSS_FLAGS) &&
2489 !(adapter->flags & UDP_RSS_FLAGS))
2490 dev_err(&adapter->pdev->dev,
2491 "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
2492
2493 adapter->flags = flags;
2494
2495 /* Perform hash on these packet types */
2496 mrqc |= E1000_MRQC_RSS_FIELD_IPV4 |
2497 E1000_MRQC_RSS_FIELD_IPV4_TCP |
2498 E1000_MRQC_RSS_FIELD_IPV6 |
2499 E1000_MRQC_RSS_FIELD_IPV6_TCP;
2500
2501 mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP |
2502 E1000_MRQC_RSS_FIELD_IPV6_UDP);
2503
2504 if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
2505 mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
2506
2507 if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
2508 mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
2509
2510 wr32(E1000_MRQC, mrqc);
2511 }
2512
2513 return 0;
2514}
2515
2516static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
2517{
2518 struct igb_adapter *adapter = netdev_priv(dev);
2519 int ret = -EOPNOTSUPP;
2520
2521 switch (cmd->cmd) {
2522 case ETHTOOL_SRXFH:
2523 ret = igb_set_rss_hash_opt(adapter, cmd);
2524 break;
2525 default:
2526 break;
2527 }
2528
2529 return ret;
2530}
2531
2353static int igb_ethtool_begin(struct net_device *netdev) 2532static int igb_ethtool_begin(struct net_device *netdev)
2354{ 2533{
2355 struct igb_adapter *adapter = netdev_priv(netdev); 2534 struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2390,6 +2569,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
2390 .get_coalesce = igb_get_coalesce, 2569 .get_coalesce = igb_get_coalesce,
2391 .set_coalesce = igb_set_coalesce, 2570 .set_coalesce = igb_set_coalesce,
2392 .get_ts_info = igb_get_ts_info, 2571 .get_ts_info = igb_get_ts_info,
2572 .get_rxnfc = igb_get_rxnfc,
2573 .set_rxnfc = igb_set_rxnfc,
2393 .begin = igb_ethtool_begin, 2574 .begin = igb_ethtool_begin,
2394 .complete = igb_ethtool_complete, 2575 .complete = igb_ethtool_complete,
2395}; 2576};
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 082ce73dc627..da9fd7b8e23a 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2874,18 +2874,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
2874 2874
2875 /* Don't need to set TUOFL or IPOFL, they default to 1 */ 2875 /* Don't need to set TUOFL or IPOFL, they default to 1 */
2876 wr32(E1000_RXCSUM, rxcsum); 2876 wr32(E1000_RXCSUM, rxcsum);
2877 /*
2878 * Generate RSS hash based on TCP port numbers and/or
2879 * IPv4/v6 src and dst addresses since UDP cannot be
2880 * hashed reliably due to IP fragmentation
2881 */
2882 2877
2878 /* Generate RSS hash based on packet types, TCP/UDP
2879 * port numbers and/or IPv4/v6 src and dst addresses
2880 */
2883 mrqc = E1000_MRQC_RSS_FIELD_IPV4 | 2881 mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
2884 E1000_MRQC_RSS_FIELD_IPV4_TCP | 2882 E1000_MRQC_RSS_FIELD_IPV4_TCP |
2885 E1000_MRQC_RSS_FIELD_IPV6 | 2883 E1000_MRQC_RSS_FIELD_IPV6 |
2886 E1000_MRQC_RSS_FIELD_IPV6_TCP | 2884 E1000_MRQC_RSS_FIELD_IPV6_TCP |
2887 E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; 2885 E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
2888 2886
2887 if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
2888 mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
2889 if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
2890 mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
2891
2889 /* If VMDq is enabled then we set the appropriate mode for that, else 2892 /* If VMDq is enabled then we set the appropriate mode for that, else
2890 * we default to RSS so that an RSS hash is calculated per packet even 2893 * we default to RSS so that an RSS hash is calculated per packet even
2891 * if we are only using one queue */ 2894 * if we are only using one queue */