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:
commit
b44beb8ae5
|
@ -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",
|
||||
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;
|
||||
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue