]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
fm10k: future-proof state bitmaps using DECLARE_BITMAP
[karo-tx-linux.git] / drivers / net / ethernet / intel / fm10k / fm10k_ethtool.c
index 0c84fef750f43a2c9230a580003bbd9b9a5d4ef9..c7234f35f8ff3462dc667a01dafd10208dcc9d82 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel(R) Ethernet Switch Host Interface Driver
- * Copyright(c) 2013 - 2016 Intel Corporation.
+ * Copyright(c) 2013 - 2017 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -562,7 +562,7 @@ static int fm10k_set_ringparam(struct net_device *netdev,
                return 0;
        }
 
-       while (test_and_set_bit(__FM10K_RESETTING, &interface->state))
+       while (test_and_set_bit(__FM10K_RESETTING, interface->state))
                usleep_range(1000, 2000);
 
        if (!netif_running(interface->netdev)) {
@@ -648,7 +648,7 @@ err_setup:
        fm10k_up(interface);
        vfree(temp_ring);
 clear_reset:
-       clear_bit(__FM10K_RESETTING, &interface->state);
+       clear_bit(__FM10K_RESETTING, interface->state);
        return err;
 }
 
@@ -716,7 +716,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
                cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
                /* fall through */
        case UDP_V4_FLOW:
-               if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP)
+               if (test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                            interface->flags))
                        cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
                /* fall through */
        case SCTP_V4_FLOW:
@@ -732,7 +733,8 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
                cmd->data |= RXH_IP_SRC | RXH_IP_DST;
                break;
        case UDP_V6_FLOW:
-               if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP)
+               if (test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                            interface->flags))
                        cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
                cmd->data |= RXH_IP_SRC | RXH_IP_DST;
                break;
@@ -764,12 +766,13 @@ static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
        return ret;
 }
 
-#define UDP_RSS_FLAGS (FM10K_FLAG_RSS_FIELD_IPV4_UDP | \
-                      FM10K_FLAG_RSS_FIELD_IPV6_UDP)
 static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
                                  struct ethtool_rxnfc *nfc)
 {
-       u32 flags = interface->flags;
+       int rss_ipv4_udp = test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                                   interface->flags);
+       int rss_ipv6_udp = test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                                   interface->flags);
 
        /* RSS does not support anything other than hashing
         * to queues on src and dst IPs and ports
@@ -793,10 +796,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
                        return -EINVAL;
                switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
                case 0:
-                       flags &= ~FM10K_FLAG_RSS_FIELD_IPV4_UDP;
+                       clear_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                                 interface->flags);
                        break;
                case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
-                       flags |= FM10K_FLAG_RSS_FIELD_IPV4_UDP;
+                       set_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                               interface->flags);
                        break;
                default:
                        return -EINVAL;
@@ -808,10 +813,12 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
                        return -EINVAL;
                switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
                case 0:
-                       flags &= ~FM10K_FLAG_RSS_FIELD_IPV6_UDP;
+                       clear_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                                 interface->flags);
                        break;
                case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
-                       flags |= FM10K_FLAG_RSS_FIELD_IPV6_UDP;
+                       set_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                               interface->flags);
                        break;
                default:
                        return -EINVAL;
@@ -835,28 +842,41 @@ static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
                return -EINVAL;
        }
 
-       /* if we changed something we need to update flags */
-       if (flags != interface->flags) {
+       /* If something changed we need to update the MRQC register. Note that
+        * test_bit() is guaranteed to return strictly 0 or 1, so testing for
+        * equality is safe.
+        */
+       if ((rss_ipv4_udp != test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                                     interface->flags)) ||
+           (rss_ipv6_udp != test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                                     interface->flags))) {
                struct fm10k_hw *hw = &interface->hw;
+               bool warn = false;
                u32 mrqc;
 
-               if ((flags & UDP_RSS_FLAGS) &&
-                   !(interface->flags & UDP_RSS_FLAGS))
-                       netif_warn(interface, drv, interface->netdev,
-                                  "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
-
-               interface->flags = flags;
-
                /* Perform hash on these packet types */
                mrqc = FM10K_MRQC_IPV4 |
                       FM10K_MRQC_TCP_IPV4 |
                       FM10K_MRQC_IPV6 |
                       FM10K_MRQC_TCP_IPV6;
 
-               if (flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP)
+               if (test_bit(FM10K_FLAG_RSS_FIELD_IPV4_UDP,
+                            interface->flags)) {
                        mrqc |= FM10K_MRQC_UDP_IPV4;
-               if (flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP)
+                       warn = true;
+               }
+               if (test_bit(FM10K_FLAG_RSS_FIELD_IPV6_UDP,
+                            interface->flags)) {
                        mrqc |= FM10K_MRQC_UDP_IPV6;
+                       warn = true;
+               }
+
+               /* If we enable UDP RSS display a warning that this may cause
+                * fragmented UDP packets to arrive out of order.
+                */
+               if (warn)
+                       netif_warn(interface, drv, interface->netdev,
+                                  "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
 
                fm10k_write_reg(hw, FM10K_MRQC(0), mrqc);
        }
@@ -939,7 +959,7 @@ static void fm10k_self_test(struct net_device *dev,
 
        memset(data, 0, sizeof(*data) * FM10K_TEST_LEN);
 
-       if (FM10K_REMOVED(hw)) {
+       if (FM10K_REMOVED(hw->hw_addr)) {
                netif_err(interface, drv, dev,
                          "Interface removed - test blocked\n");
                eth_test->flags |= ETH_TEST_FL_FAILED;