Skip to content

Commit

Permalink
Merge branch 'Bug-fixes-for-ENA-Ethernet-driver'
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
davem330 committed Feb 12, 2020
2 parents 457fed7 + c207979 commit b44beb8
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 44 deletions.
96 changes: 58 additions & 38 deletions drivers/net/ethernet/amazon/ena/ena_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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)) {
pr_err("command id is larger than the queue size. cmd_id: %u queue size %d\n",
command_id, queue->q_depth);
Expand Down Expand Up @@ -1041,9 +1046,41 @@ static int ena_com_get_feature(struct ena_com_dev *ena_dev,
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)
{
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 =
dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
Expand Down Expand Up @@ -1254,30 +1291,6 @@ static int ena_com_ind_tbl_convert_to_device(struct ena_com_dev *ena_dev)
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,
u16 intr_delay_resolution)
{
Expand Down Expand Up @@ -2297,15 +2310,16 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,

switch (func) {
case ENA_ADMIN_TOEPLITZ:
if (key_len > sizeof(hash_key->key)) {
pr_err("key len (%hu) is bigger than the max supported (%zu)\n",
key_len, sizeof(hash_key->key));
return -EINVAL;
if (key) {
if (key_len != sizeof(hash_key->key)) {
pr_err("key len (%hu) doesn't equal the supported size (%zu)\n",
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;
case ENA_ADMIN_CRC32:
rss->hash_init_val = init_val;
Expand Down Expand Up @@ -2342,7 +2356,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;
/* 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)
*func = rss->hash_func;

Expand Down Expand Up @@ -2606,10 +2624,6 @@ int ena_com_indirect_table_get(struct ena_com_dev *ena_dev, u32 *ind_tbl)
if (!ind_tbl)
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++)
ind_tbl[i] = rss->host_rss_ind_tbl[i];

Expand All @@ -2626,9 +2640,15 @@ int ena_com_rss_init(struct ena_com_dev *ena_dev, u16 indr_tbl_log_size)
if (unlikely(rc))
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);
if (unlikely(rc))
if (unlikely(rc) && rc != -EOPNOTSUPP)
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);
if (unlikely(rc))
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/netdevice.h>

#include "ena_common_defs.h"
#include "ena_admin_defs.h"
Expand Down Expand Up @@ -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);

/* 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_dev: ENA communication layer struct
* @func: The hash function (Toeplitz or crc)
Expand Down
46 changes: 43 additions & 3 deletions drivers/net/ethernet/amazon/ena/ena_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,28 @@ static u32 ena_get_rxfh_key_size(struct net_device *netdev)
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,
u8 *hfunc)
{
Expand All @@ -644,11 +666,25 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 func;
int rc;

rc = ena_com_indirect_table_get(adapter->ena_dev, indir);
rc = ena_indirection_table_get(adapter, indir);
if (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);

if (rc) {
if (rc == -EOPNOTSUPP) {
key = NULL;
hfunc = NULL;
rc = 0;
}

return rc;
}

if (rc)
return rc;

Expand All @@ -657,7 +693,7 @@ static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
func = ETH_RSS_HASH_TOP;
break;
case ENA_ADMIN_CRC32:
func = ETH_RSS_HASH_XOR;
func = ETH_RSS_HASH_CRC32;
break;
default:
netif_err(adapter, drv, netdev,
Expand Down Expand Up @@ -700,10 +736,13 @@ static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
}

switch (hfunc) {
case ETH_RSS_HASH_NO_CHANGE:
func = ena_com_get_current_hash_function(ena_dev);
break;
case ETH_RSS_HASH_TOP:
func = ENA_ADMIN_TOEPLITZ;
break;
case ETH_RSS_HASH_XOR:
case ETH_RSS_HASH_CRC32:
func = ENA_ADMIN_CRC32;
break;
default:
Expand Down Expand Up @@ -814,6 +853,7 @@ static const struct ethtool_ops ena_ethtool_ops = {
.set_channels = ena_set_channels,
.get_tunable = ena_get_tunable,
.set_tunable = ena_set_tunable,
.get_ts_info = ethtool_op_get_ts_info,
};

void ena_set_ethtool_ops(struct net_device *netdev)
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ethernet/amazon/ena/ena_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
return;

keep_alive_expired = round_jiffies(adapter->last_keep_alive_jiffies +
adapter->keep_alive_timeout);
keep_alive_expired = adapter->last_keep_alive_jiffies +
adapter->keep_alive_timeout;
if (unlikely(time_is_before_jiffies(keep_alive_expired))) {
netif_err(adapter, drv, adapter->netdev,
"Keep alive watchdog timeout.\n");
Expand Down Expand Up @@ -3809,7 +3809,7 @@ static void ena_timer_service(struct timer_list *t)
}

/* 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,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@

#define ENA_IO_TXQ_IDX(q) (2 * (q))
#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_IO_IRQ_FIRST_IDX 1
Expand Down

0 comments on commit b44beb8

Please sign in to comment.