Merge branch 'Bug-fixes-for-ENA-Ethernet-driver'

Sameeh Jubran says:

====================
Bug fixes for ENA Ethernet driver

Difference from V1:
* Started using netdev_rss_key_fill()
* Dropped superflous changes that are not related to bug fixes as
  requested by Jakub
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-02-11 17:08:31 -08:00
commit b44beb8ae5
5 changed files with 115 additions and 44 deletions

View File

@ -200,6 +200,11 @@ static void comp_ctxt_release(struct ena_com_admin_queue *queue,
static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue, static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue,
u16 command_id, bool capture) u16 command_id, bool capture)
{ {
if (unlikely(!queue->comp_ctx)) {
pr_err("Completion context is NULL\n");
return NULL;
}
if (unlikely(command_id >= queue->q_depth)) { if (unlikely(command_id >= queue->q_depth)) {
pr_err("command id is larger than the queue size. cmd_id: %u queue size %d\n", pr_err("command id is larger than the queue size. cmd_id: %u queue size %d\n",
command_id, queue->q_depth); command_id, queue->q_depth);
@ -1041,9 +1046,41 @@ static int ena_com_get_feature(struct ena_com_dev *ena_dev,
feature_ver); feature_ver);
} }
int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev)
{
return ena_dev->rss.hash_func;
}
static void ena_com_hash_key_fill_default_key(struct ena_com_dev *ena_dev)
{
struct ena_admin_feature_rss_flow_hash_control *hash_key =
(ena_dev->rss).hash_key;
netdev_rss_key_fill(&hash_key->key, sizeof(hash_key->key));
/* The key is stored in the device in u32 array
* as well as the API requires the key to be passed in this
* format. Thus the size of our array should be divided by 4
*/
hash_key->keys_num = sizeof(hash_key->key) / sizeof(u32);
}
static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev) static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
{ {
struct ena_rss *rss = &ena_dev->rss; 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;
int rc;
hash_key = (ena_dev->rss).hash_key;
rc = ena_com_get_feature_ex(ena_dev, &get_resp,
ENA_ADMIN_RSS_HASH_FUNCTION,
ena_dev->rss.hash_key_dma_addr,
sizeof(ena_dev->rss.hash_key), 0);
if (unlikely(rc)) {
hash_key = NULL;
return -EOPNOTSUPP;
}
rss->hash_key = rss->hash_key =
dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key), dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
@ -1254,30 +1291,6 @@ static int ena_com_ind_tbl_convert_to_device(struct ena_com_dev *ena_dev)
return 0; return 0;
} }
static int ena_com_ind_tbl_convert_from_device(struct ena_com_dev *ena_dev)
{
u16 dev_idx_to_host_tbl[ENA_TOTAL_NUM_QUEUES] = { (u16)-1 };
struct ena_rss *rss = &ena_dev->rss;
u8 idx;
u16 i;
for (i = 0; i < ENA_TOTAL_NUM_QUEUES; i++)
dev_idx_to_host_tbl[ena_dev->io_sq_queues[i].idx] = i;
for (i = 0; i < 1 << rss->tbl_log_size; i++) {
if (rss->rss_ind_tbl[i].cq_idx > ENA_TOTAL_NUM_QUEUES)
return -EINVAL;
idx = (u8)rss->rss_ind_tbl[i].cq_idx;
if (dev_idx_to_host_tbl[idx] > ENA_TOTAL_NUM_QUEUES)
return -EINVAL;
rss->host_rss_ind_tbl[i] = dev_idx_to_host_tbl[idx];
}
return 0;
}
static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev, static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev,
u16 intr_delay_resolution) u16 intr_delay_resolution)
{ {
@ -2297,15 +2310,16 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
switch (func) { switch (func) {
case ENA_ADMIN_TOEPLITZ: case ENA_ADMIN_TOEPLITZ:
if (key_len > sizeof(hash_key->key)) { if (key) {
pr_err("key len (%hu) is bigger than the max supported (%zu)\n", if (key_len != sizeof(hash_key->key)) {
key_len, sizeof(hash_key->key)); pr_err("key len (%hu) doesn't equal the supported size (%zu)\n",
return -EINVAL; key_len, sizeof(hash_key->key));
return -EINVAL;
}
memcpy(hash_key->key, key, key_len);
rss->hash_init_val = init_val;
hash_key->keys_num = key_len >> 2;
} }
memcpy(hash_key->key, key, key_len);
rss->hash_init_val = init_val;
hash_key->keys_num = key_len >> 2;
break; break;
case ENA_ADMIN_CRC32: case ENA_ADMIN_CRC32:
rss->hash_init_val = init_val; rss->hash_init_val = init_val;
@ -2342,7 +2356,11 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
if (unlikely(rc)) if (unlikely(rc))
return rc; return rc;
rss->hash_func = get_resp.u.flow_hash_func.selected_func; /* ffs() returns 1 in case the lsb is set */
rss->hash_func = ffs(get_resp.u.flow_hash_func.selected_func);
if (rss->hash_func)
rss->hash_func--;
if (func) if (func)
*func = rss->hash_func; *func = rss->hash_func;
@ -2606,10 +2624,6 @@ int ena_com_indirect_table_get(struct ena_com_dev *ena_dev, u32 *ind_tbl)
if (!ind_tbl) if (!ind_tbl)
return 0; return 0;
rc = ena_com_ind_tbl_convert_from_device(ena_dev);
if (unlikely(rc))
return rc;
for (i = 0; i < (1 << rss->tbl_log_size); i++) for (i = 0; i < (1 << rss->tbl_log_size); i++)
ind_tbl[i] = rss->host_rss_ind_tbl[i]; ind_tbl[i] = rss->host_rss_ind_tbl[i];
@ -2626,9 +2640,15 @@ int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 indr_tbl_log_size)
if (unlikely(rc)) if (unlikely(rc))
goto err_indr_tbl; goto err_indr_tbl;
/* The following function might return unsupported in case the
* device doesn't support setting the key / hash function. We can safely
* ignore this error and have indirection table support only.
*/
rc = ena_com_hash_key_allocate(ena_dev); rc = ena_com_hash_key_allocate(ena_dev);
if (unlikely(rc)) if (unlikely(rc) && rc != -EOPNOTSUPP)
goto err_hash_key; goto err_hash_key;
else if (rc != -EOPNOTSUPP)
ena_com_hash_key_fill_default_key(ena_dev);
rc = ena_com_hash_ctrl_init(ena_dev); rc = ena_com_hash_ctrl_init(ena_dev);
if (unlikely(rc)) if (unlikely(rc))

View File

@ -44,6 +44,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/netdevice.h>
#include "ena_common_defs.h" #include "ena_common_defs.h"
#include "ena_admin_defs.h" #include "ena_admin_defs.h"
@ -655,6 +656,14 @@ int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 log_size);
*/ */
void ena_com_rss_destroy(struct ena_com_dev *ena_dev); void ena_com_rss_destroy(struct ena_com_dev *ena_dev);
/* ena_com_get_current_hash_function - Get RSS hash function
* @ena_dev: ENA communication layer struct
*
* Return the current hash function.
* @return: 0 or one of the ena_admin_hash_functions values.
*/
int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev);
/* ena_com_fill_hash_function - Fill RSS hash function /* ena_com_fill_hash_function - Fill RSS hash function
* @ena_dev: ENA communication layer struct * @ena_dev: ENA communication layer struct
* @func: The hash function (Toeplitz or crc) * @func: The hash function (Toeplitz or crc)

View File

@ -636,6 +636,28 @@ static u32 ena_get_rxfh_key_size(struct net_device *netdev)
return ENA_HASH_KEY_SIZE; return ENA_HASH_KEY_SIZE;
} }
static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir)
{
struct ena_com_dev *ena_dev = adapter->ena_dev;
int i, rc;
if (!indir)
return 0;
rc = ena_com_indirect_table_get(ena_dev, indir);
if (rc)
return rc;
/* Our internal representation of the indices is: even indices
* for Tx and uneven indices for Rx. We need to convert the Rx
* indices to be consecutive
*/
for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++)
indir[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(indir[i]);
return rc;
}
static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc) u8 *hfunc)
{ {
@ -644,11 +666,25 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 func; u8 func;
int rc; int rc;
rc = ena_com_indirect_table_get(adapter->ena_dev, indir); rc = ena_indirection_table_get(adapter, indir);
if (rc) if (rc)
return rc; return rc;
/* We call this function in order to check if the device
* supports getting/setting the hash function.
*/
rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func, key); rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func, key);
if (rc) {
if (rc == -EOPNOTSUPP) {
key = NULL;
hfunc = NULL;
rc = 0;
}
return rc;
}
if (rc) if (rc)
return rc; return rc;
@ -657,7 +693,7 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
func = ETH_RSS_HASH_TOP; func = ETH_RSS_HASH_TOP;
break; break;
case ENA_ADMIN_CRC32: case ENA_ADMIN_CRC32:
func = ETH_RSS_HASH_XOR; func = ETH_RSS_HASH_CRC32;
break; break;
default: default:
netif_err(adapter, drv, netdev, netif_err(adapter, drv, netdev,
@ -700,10 +736,13 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
} }
switch (hfunc) { switch (hfunc) {
case ETH_RSS_HASH_NO_CHANGE:
func = ena_com_get_current_hash_function(ena_dev);
break;
case ETH_RSS_HASH_TOP: case ETH_RSS_HASH_TOP:
func = ENA_ADMIN_TOEPLITZ; func = ENA_ADMIN_TOEPLITZ;
break; break;
case ETH_RSS_HASH_XOR: case ETH_RSS_HASH_CRC32:
func = ENA_ADMIN_CRC32; func = ENA_ADMIN_CRC32;
break; break;
default: default:
@ -814,6 +853,7 @@ static const struct ethtool_ops ena_ethtool_ops = {
.set_channels = ena_set_channels, .set_channels = ena_set_channels,
.get_tunable = ena_get_tunable, .get_tunable = ena_get_tunable,
.set_tunable = ena_set_tunable, .set_tunable = ena_set_tunable,
.get_ts_info = ethtool_op_get_ts_info,
}; };
void ena_set_ethtool_ops(struct net_device *netdev) void ena_set_ethtool_ops(struct net_device *netdev)

View File

@ -3706,8 +3706,8 @@ static void check_for_missing_keep_alive(struct ena_adapter *adapter)
if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT) if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT)
return; return;
keep_alive_expired = round_jiffies(adapter->last_keep_alive_jiffies + keep_alive_expired = adapter->last_keep_alive_jiffies +
adapter->keep_alive_timeout); adapter->keep_alive_timeout;
if (unlikely(time_is_before_jiffies(keep_alive_expired))) { if (unlikely(time_is_before_jiffies(keep_alive_expired))) {
netif_err(adapter, drv, adapter->netdev, netif_err(adapter, drv, adapter->netdev,
"Keep alive watchdog timeout.\n"); "Keep alive watchdog timeout.\n");
@ -3809,7 +3809,7 @@ static void ena_timer_service(struct timer_list *t)
} }
/* Reset the timer */ /* Reset the timer */
mod_timer(&adapter->timer_service, jiffies + HZ); mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
} }
static int ena_calc_max_io_queue_num(struct pci_dev *pdev, static int ena_calc_max_io_queue_num(struct pci_dev *pdev,

View File

@ -130,6 +130,8 @@
#define ENA_IO_TXQ_IDX(q) (2 * (q)) #define ENA_IO_TXQ_IDX(q) (2 * (q))
#define ENA_IO_RXQ_IDX(q) (2 * (q) + 1) #define ENA_IO_RXQ_IDX(q) (2 * (q) + 1)
#define ENA_IO_TXQ_IDX_TO_COMBINED_IDX(q) ((q) / 2)
#define ENA_IO_RXQ_IDX_TO_COMBINED_IDX(q) (((q) - 1) / 2)
#define ENA_MGMNT_IRQ_IDX 0 #define ENA_MGMNT_IRQ_IDX 0
#define ENA_IO_IRQ_FIRST_IDX 1 #define ENA_IO_IRQ_FIRST_IDX 1