Skip to content

Commit

Permalink
linux/ena update ENA linux driver to version 2.1.3
Browse files Browse the repository at this point in the history
**New Features**
* Replace old adaptive interrupt moderation algorithm with the DIM
  algorithm.
* Introduce driver_supported_features field in host_info, and use it
  to signal to the device that the driver supports adaptive interrupt
  moderation.

**Bug Fixes**
* Prevent NULL pointer dereference when an admin command is executed
  during the execution of ena_remove().
* Fix compilation error in early SUSE versions due to missing
  suse_version.h file.
* Fix continuous keep-alive resets.
* Avoid potential memory access violation by validating Rx descriptor
  req_id in the proper place.
* Fix issue where llq header size set by force_large_llq_header module
  parameter did not survive a device reset, causing a driver-device
  mismatch of header size.

Signed-off-by: Noam Dagan <[email protected]>
Signed-off-by: Sameeh Jubran <[email protected]>
Signed-off-by: Arthur Kiyanovski <[email protected]>
  • Loading branch information
akiyano committed Oct 30, 2019
1 parent 5c6afe6 commit 4cbb01d
Show file tree
Hide file tree
Showing 16 changed files with 964 additions and 652 deletions.
8 changes: 8 additions & 0 deletions kernel/linux/common/ena_com/ena_admin_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,12 @@ struct ena_admin_host_info {
u16 num_cpus;

u16 reserved;

/* 1:0 : reserved
* 2 : interrupt_moderation
* 31:3 : reserved
*/
u32 driver_supported_features;
};

struct ena_admin_rss_ind_table_entry {
Expand Down Expand Up @@ -1131,6 +1137,8 @@ struct ena_admin_ena_mmio_req_read_less_resp {
#define ENA_ADMIN_HOST_INFO_DEVICE_MASK GENMASK(7, 3)
#define ENA_ADMIN_HOST_INFO_BUS_SHIFT 8
#define ENA_ADMIN_HOST_INFO_BUS_MASK GENMASK(15, 8)
#define ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_SHIFT 2
#define ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK BIT(2)

/* feature_rss_ind_table */
#define ENA_ADMIN_FEATURE_RSS_IND_TABLE_ONE_ENTRY_UPDATE_MASK BIT(0)
Expand Down
203 changes: 35 additions & 168 deletions kernel/linux/common/ena_com/ena_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue,
return NULL;
}

if (unlikely(!queue->comp_ctx)) {
pr_err("Completion context is NULL\n");
return NULL;
}

if (unlikely(queue->comp_ctx[command_id].occupied && capture)) {
pr_err("Completion context is occupied\n");
return NULL;
Expand Down Expand Up @@ -1252,64 +1257,29 @@ 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 int ena_com_init_interrupt_moderation_table(struct ena_com_dev *ena_dev)
{
size_t size;

size = sizeof(struct ena_intr_moder_entry) * ENA_INTR_MAX_NUM_OF_LEVELS;

ena_dev->intr_moder_tbl =
devm_kzalloc(ena_dev->dmadev, size, GFP_KERNEL);
if (!ena_dev->intr_moder_tbl)
return -ENOMEM;

ena_com_config_default_interrupt_moderation_table(ena_dev);

return 0;
}

static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev,
u16 intr_delay_resolution)
{
struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;
unsigned int i;
u16 prev_intr_delay_resolution = ena_dev->intr_delay_resolution;

if (!intr_delay_resolution) {
if (unlikely(!intr_delay_resolution)) {
pr_err("Illegal intr_delay_resolution provided. Going to use default 1 usec resolution\n");
intr_delay_resolution = 1;
intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION;
}
ena_dev->intr_delay_resolution = intr_delay_resolution;

/* update Rx */
for (i = 0; i < ENA_INTR_MAX_NUM_OF_LEVELS; i++)
intr_moder_tbl[i].intr_moder_interval /= intr_delay_resolution;
ena_dev->intr_moder_rx_interval =
ena_dev->intr_moder_rx_interval *
prev_intr_delay_resolution /
intr_delay_resolution;

/* update Tx */
ena_dev->intr_moder_tx_interval /= intr_delay_resolution;
ena_dev->intr_moder_tx_interval =
ena_dev->intr_moder_tx_interval *
prev_intr_delay_resolution /
intr_delay_resolution;

ena_dev->intr_delay_resolution = intr_delay_resolution;
}

/*****************************************************************************/
Expand Down Expand Up @@ -2685,10 +2655,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 Down Expand Up @@ -2847,42 +2813,35 @@ bool ena_com_interrupt_moderation_supported(struct ena_com_dev *ena_dev)
ENA_ADMIN_INTERRUPT_MODERATION);
}

int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev,
u32 tx_coalesce_usecs)
static int ena_com_update_nonadaptive_moderation_interval(u32 coalesce_usecs,
u32 intr_delay_resolution,
u32 *intr_moder_interval)
{
if (!ena_dev->intr_delay_resolution) {
if (!intr_delay_resolution) {
pr_err("Illegal interrupt delay granularity value\n");
return -EFAULT;
}

ena_dev->intr_moder_tx_interval = tx_coalesce_usecs /
ena_dev->intr_delay_resolution;
*intr_moder_interval = coalesce_usecs / intr_delay_resolution;

return 0;
}

int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev,
u32 rx_coalesce_usecs)
{
if (!ena_dev->intr_delay_resolution) {
pr_err("Illegal interrupt delay granularity value\n");
return -EFAULT;
}

/* We use LOWEST entry of moderation table for storing
* nonadaptive interrupt coalescing values
*/
ena_dev->intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval =
rx_coalesce_usecs / ena_dev->intr_delay_resolution;

return 0;
int ena_com_update_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev,
u32 tx_coalesce_usecs)
{
return ena_com_update_nonadaptive_moderation_interval(tx_coalesce_usecs,
ena_dev->intr_delay_resolution,
&ena_dev->intr_moder_tx_interval);
}

void ena_com_destroy_interrupt_moderation(struct ena_com_dev *ena_dev)
int ena_com_update_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev,
u32 rx_coalesce_usecs)
{
if (ena_dev->intr_moder_tbl)
devm_kfree(ena_dev->dmadev, ena_dev->intr_moder_tbl);
ena_dev->intr_moder_tbl = NULL;
return ena_com_update_nonadaptive_moderation_interval(rx_coalesce_usecs,
ena_dev->intr_delay_resolution,
&ena_dev->intr_moder_rx_interval);
}

int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
Expand All @@ -2909,10 +2868,6 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
return rc;
}

rc = ena_com_init_interrupt_moderation_table(ena_dev);
if (rc)
goto err;

/* if moderation is supported by device we set adaptive moderation */
delay_resolution = get_resp.u.intr_moderation.intr_delay_resolution;
ena_com_update_intr_delay_resolution(ena_dev, delay_resolution);
Expand All @@ -2921,52 +2876,6 @@ int ena_com_init_interrupt_moderation(struct ena_com_dev *ena_dev)
ena_com_disable_adaptive_moderation(ena_dev);

return 0;
err:
ena_com_destroy_interrupt_moderation(ena_dev);
return rc;
}

void ena_com_config_default_interrupt_moderation_table(struct ena_com_dev *ena_dev)
{
struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;

if (!intr_moder_tbl)
return;

intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval =
ENA_INTR_LOWEST_USECS;
intr_moder_tbl[ENA_INTR_MODER_LOWEST].pkts_per_interval =
ENA_INTR_LOWEST_PKTS;
intr_moder_tbl[ENA_INTR_MODER_LOWEST].bytes_per_interval =
ENA_INTR_LOWEST_BYTES;

intr_moder_tbl[ENA_INTR_MODER_LOW].intr_moder_interval =
ENA_INTR_LOW_USECS;
intr_moder_tbl[ENA_INTR_MODER_LOW].pkts_per_interval =
ENA_INTR_LOW_PKTS;
intr_moder_tbl[ENA_INTR_MODER_LOW].bytes_per_interval =
ENA_INTR_LOW_BYTES;

intr_moder_tbl[ENA_INTR_MODER_MID].intr_moder_interval =
ENA_INTR_MID_USECS;
intr_moder_tbl[ENA_INTR_MODER_MID].pkts_per_interval =
ENA_INTR_MID_PKTS;
intr_moder_tbl[ENA_INTR_MODER_MID].bytes_per_interval =
ENA_INTR_MID_BYTES;

intr_moder_tbl[ENA_INTR_MODER_HIGH].intr_moder_interval =
ENA_INTR_HIGH_USECS;
intr_moder_tbl[ENA_INTR_MODER_HIGH].pkts_per_interval =
ENA_INTR_HIGH_PKTS;
intr_moder_tbl[ENA_INTR_MODER_HIGH].bytes_per_interval =
ENA_INTR_HIGH_BYTES;

intr_moder_tbl[ENA_INTR_MODER_HIGHEST].intr_moder_interval =
ENA_INTR_HIGHEST_USECS;
intr_moder_tbl[ENA_INTR_MODER_HIGHEST].pkts_per_interval =
ENA_INTR_HIGHEST_PKTS;
intr_moder_tbl[ENA_INTR_MODER_HIGHEST].bytes_per_interval =
ENA_INTR_HIGHEST_BYTES;
}

unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *ena_dev)
Expand All @@ -2976,49 +2885,7 @@ unsigned int ena_com_get_nonadaptive_moderation_interval_tx(struct ena_com_dev *

unsigned int ena_com_get_nonadaptive_moderation_interval_rx(struct ena_com_dev *ena_dev)
{
struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;

if (intr_moder_tbl)
return intr_moder_tbl[ENA_INTR_MODER_LOWEST].intr_moder_interval;

return 0;
}

void ena_com_init_intr_moderation_entry(struct ena_com_dev *ena_dev,
enum ena_intr_moder_level level,
struct ena_intr_moder_entry *entry)
{
struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;

if (level >= ENA_INTR_MAX_NUM_OF_LEVELS)
return;

intr_moder_tbl[level].intr_moder_interval = entry->intr_moder_interval;
if (ena_dev->intr_delay_resolution)
intr_moder_tbl[level].intr_moder_interval /=
ena_dev->intr_delay_resolution;
intr_moder_tbl[level].pkts_per_interval = entry->pkts_per_interval;

/* use hardcoded value until ethtool supports bytecount parameter */
if (entry->bytes_per_interval != ENA_INTR_BYTE_COUNT_NOT_SUPPORTED)
intr_moder_tbl[level].bytes_per_interval = entry->bytes_per_interval;
}

void ena_com_get_intr_moderation_entry(struct ena_com_dev *ena_dev,
enum ena_intr_moder_level level,
struct ena_intr_moder_entry *entry)
{
struct ena_intr_moder_entry *intr_moder_tbl = ena_dev->intr_moder_tbl;

if (level >= ENA_INTR_MAX_NUM_OF_LEVELS)
return;

entry->intr_moder_interval = intr_moder_tbl[level].intr_moder_interval;
if (ena_dev->intr_delay_resolution)
entry->intr_moder_interval *= ena_dev->intr_delay_resolution;
entry->pkts_per_interval =
intr_moder_tbl[level].pkts_per_interval;
entry->bytes_per_interval = intr_moder_tbl[level].bytes_per_interval;
return ena_dev->intr_moder_rx_interval;
}

int ena_com_config_dev_mode(struct ena_com_dev *ena_dev,
Expand Down
Loading

0 comments on commit 4cbb01d

Please sign in to comment.