net/ena/base: fix testing for supported hash function
authorMichal Krawczyk <mk@semihalf.com>
Wed, 8 Apr 2020 08:28:56 +0000 (10:28 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:06 +0000 (13:57 +0200)
There was a bug in ena_com_fill_hash_function(), which was causing bit to
be shifted left one bit too much.

To fix that, the ENA_FFS macro is being used (returning the location of
the first bit set), hash_function value is being subtracted by 1 if any
hash function is supported by the device and BIT macro is used for
shifting for better verbosity.

Fixes: 99ecfbf845b3 ("ena: import communication layer")
Cc: stable@dpdk.org
Signed-off-by: Michal Krawczyk <mk@semihalf.com>
drivers/net/ena/base/ena_com.c
drivers/net/ena/base/ena_plat_dpdk.h

index 38a474b..04f5d21 100644 (file)
@@ -2394,12 +2394,14 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
                               enum ena_admin_hash_functions func,
                               const u8 *key, u16 key_len, u32 init_val)
 {
-       struct ena_rss *rss = &ena_dev->rss;
+       struct ena_admin_feature_rss_flow_hash_control *hash_key;
        struct ena_admin_get_feat_resp get_resp;
-       struct ena_admin_feature_rss_flow_hash_control *hash_key =
-               rss->hash_key;
+       enum ena_admin_hash_functions old_func;
+       struct ena_rss *rss = &ena_dev->rss;
        int rc;
 
+       hash_key = rss->hash_key;
+
        /* Make sure size is a mult of DWs */
        if (unlikely(key_len & 0x3))
                return ENA_COM_INVAL;
@@ -2411,7 +2413,7 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
        if (unlikely(rc))
                return rc;
 
-       if (!((1 << func) & get_resp.u.flow_hash_func.supported_func)) {
+       if (!(BIT(func) & get_resp.u.flow_hash_func.supported_func)) {
                ena_trc_err("Flow hash function %d isn't supported\n", func);
                return ENA_COM_UNSUPPORTED;
        }
@@ -2437,12 +2439,13 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
                return ENA_COM_INVAL;
        }
 
+       old_func = rss->hash_func;
        rss->hash_func = func;
        rc = ena_com_set_hash_function(ena_dev);
 
        /* Restore the old function */
        if (unlikely(rc))
-               ena_com_get_hash_function(ena_dev, NULL, NULL);
+               rss->hash_func = old_func;
 
        return rc;
 }
@@ -2464,7 +2467,11 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
        if (unlikely(rc))
                return rc;
 
-       rss->hash_func = get_resp.u.flow_hash_func.selected_func;
+       /* ENA_FFS returns 1 in case the lsb is set */
+       rss->hash_func = ENA_FFS(get_resp.u.flow_hash_func.selected_func);
+       if (rss->hash_func)
+               rss->hash_func--;
+
        if (func)
                *func = rss->hash_func;
 
index e9b33bc..e9b3c02 100644 (file)
@@ -301,6 +301,8 @@ extern rte_atomic32_t ena_alloc_cnt;
 
 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
 
+#define ENA_FFS(x) ffs(x)
+
 void ena_rss_key_fill(void *key, size_t size);
 
 #define ENA_RSS_FILL_KEY(key, size) ena_rss_key_fill(key, size)