Commit b44beb8a authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 457fed77 c207979f
Loading
Loading
Loading
Loading
+58 −38
Original line number Diff line number Diff line
@@ -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);
@@ -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),
@@ -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)
{
@@ -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",
		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;
		}
		break;
	case ENA_ADMIN_CRC32:
		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))
		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;

@@ -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];

@@ -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))
+9 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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)
+43 −3
Original line number Diff line number Diff line
@@ -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)
{
@@ -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;

@@ -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,
@@ -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:
@@ -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)
+3 −3
Original line number Diff line number Diff line
@@ -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");
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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