Permalink
Browse files

update ena driver to version 1.1.2

Changes from our previous release (1.0.2):
New Features:
* Add ndo busy poll callback, that will typically reduce network latency.
* Use napi_schedule_irqoff when possible
* move from ena_trc_* to pr_* functions and ENA_ASSERT to WARN
* Indentations and fix comments structure
* Add prefetch to the driver
* Add hardware hints
* Remove affinity hints in the driver, allowing the irq balancer to move
        it depending on the load.
        Developers can still override affinity using /proc/irq/*/smp_affinity

Bug Fixes:
* Initialized last_keep_alive_jiffies
        Can cause watchdog reset if the value isn't initialized
        After this watchdog driver reset it initiated, it will not happen again
        while the OS is running.
* Reorder the initialization of the workqueues and the timer service
        In the highly unlikely event of driver failing on probe the reset workqueue
        cause access to freed aread.
* Remove redundant logic in napi callback for busy poll mode.
        Impact the performance on kernel >= 4.5 when CONFIG_NET_RX_BUSY_POLL is enable
                and socket is openned with SO_BUSY_POLL
* In RSS hash configuration add missing variable initialization.
* Fix type mismatch in structs initialization
* Fix kernel starvation when get_statistics is called from atomic context
* Fix potential memory corruption during reset and restart flow.
* Fix kernel panic when driver reset fail

Minor changes:
* Reduce the number of printouts
* Move printing of unsupported negotiated feature to _dbg instead of _notice
* Increase default admin timeout to 3 sec and Keep-Alive to 5 sec.
* Change the behaiver of Tx xmit in case of an error.
        drop the packet and return NETDEV_TX_OK instead of retunring NETDEV_TX_BUSY
  • Loading branch information...
Netanel Belgazal
Netanel Belgazal committed Dec 8, 2016
1 parent b594ac1 commit a485656091e2c826c55b2202f72a81ac435ba2e8

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -33,6 +33,7 @@
#ifndef ENA_COM
#define ENA_COM
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
@@ -47,24 +48,8 @@
#include "ena_eth_io_defs.h"
#include "ena_regs_defs.h"
#define ena_trc_dbg(format, arg...) \
pr_debug("[ENA_COM: %s] " format, __func__, ##arg)
#define ena_trc_info(format, arg...) \
pr_info("[ENA_COM: %s] " format, __func__, ##arg)
#define ena_trc_warn(format, arg...) \
pr_warn("[ENA_COM: %s] " format, __func__, ##arg)
#define ena_trc_err(format, arg...) \
pr_err("[ENA_COM: %s] " format, __func__, ##arg)
#define ENA_ASSERT(cond, format, arg...) \
do { \
if (unlikely(!(cond))) { \
ena_trc_err( \
"Assert failed on %s:%s:%d:" format, \
__FILE__, __func__, __LINE__, ##arg); \
WARN_ON(!(cond)); \
} \
} while (0)
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define ENA_MAX_NUM_IO_QUEUES 128U
/* We need to queues for each IO (on for Tx and one for Rx) */
@@ -109,6 +94,10 @@
#define ENA_INTR_INITIAL_RX_INTERVAL_USECS 4
#define ENA_INTR_DELAY_OLD_VALUE_WEIGHT 6
#define ENA_INTR_DELAY_NEW_VALUE_WEIGHT 4
#define ENA_INTR_MODER_LEVEL_STRIDE 1
#define ENA_INTR_BYTE_COUNT_NOT_SUPPORTED 0xFFFFFF
#define ENA_HW_HINTS_NO_TIMEOUT 0xFFFF
enum ena_intr_moder_level {
ENA_INTR_MODER_LOWEST = 0,
@@ -141,8 +130,8 @@ struct ena_com_rx_buf_info {
};
struct ena_com_io_desc_addr {
u8 __iomem *pbuf_dev_addr; /* LLQ address */
u8 *virt_addr;
u8 __iomem *pbuf_dev_addr; /* LLQ address */
u8 *virt_addr;
dma_addr_t phys_addr;
};
@@ -246,6 +235,7 @@ struct ena_com_admin_queue {
void *q_dmadev;
spinlock_t q_lock; /* spinlock for the admin queue */
struct ena_comp_ctx *comp_ctx;
u32 completion_timeout;
u16 q_depth;
struct ena_com_admin_cq cq;
struct ena_com_admin_sq sq;
@@ -280,6 +270,7 @@ struct ena_com_aenq {
struct ena_com_mmio_read {
struct ena_admin_ena_mmio_req_read_less_resp *read_resp;
dma_addr_t read_resp_dma_addr;
u32 reg_read_to; /* in us */
u16 seq_num;
bool readless_supported;
/* spin lock to ensure a single outstanding read */
@@ -349,6 +340,7 @@ struct ena_com_dev_get_features_ctx {
struct ena_admin_device_attr_feature_desc dev_attr;
struct ena_admin_feature_aenq_desc aenq;
struct ena_admin_feature_offload_desc offload;
struct ena_admin_ena_hw_hints hw_hints;
};
struct ena_com_create_io_ctx {
@@ -385,7 +377,7 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev);
/* ena_com_set_mmio_read_mode - Enable/disable the mmio reg read mechanism
* @ena_dev: ENA communication layer struct
* @realess_supported: readless mode (enable/disable)
* @readless_supported: readless mode (enable/disable)
*/
void ena_com_set_mmio_read_mode(struct ena_com_dev *ena_dev,
bool readless_supported);
@@ -434,7 +426,7 @@ int ena_com_dev_reset(struct ena_com_dev *ena_dev);
/* ena_com_create_io_queue - Create io queue.
* @ena_dev: ENA communication layer struct
* ena_com_create_io_ctx - create context structure
* @ctx - create context structure
*
* Create the submission and the completion queues.
*
@@ -443,8 +435,9 @@ int ena_com_dev_reset(struct ena_com_dev *ena_dev);
int ena_com_create_io_queue(struct ena_com_dev *ena_dev,
struct ena_com_create_io_ctx *ctx);
/* ena_com_admin_destroy - Destroy IO queue with the queue id - qid.
/* ena_com_destroy_io_queue - Destroy IO queue with the queue id - qid.
* @ena_dev: ENA communication layer struct
* @qid - the caller virtual queue id.
*/
void ena_com_destroy_io_queue(struct ena_com_dev *ena_dev, u16 qid);
@@ -985,8 +978,8 @@ static inline void ena_com_calculate_interrupt_delay(struct ena_com_dev *ena_dev
return;
curr_moder_idx = (enum ena_intr_moder_level)(*moder_tbl_idx);
if (unlikely(curr_moder_idx >= ENA_INTR_MAX_NUM_OF_LEVELS)) {
ena_trc_err("Wrong moderation index %u\n", curr_moder_idx);
if (unlikely(curr_moder_idx >= ENA_INTR_MAX_NUM_OF_LEVELS)) {
pr_err("Wrong moderation index %u\n", curr_moder_idx);
return;
}
@@ -997,19 +990,19 @@ static inline void ena_com_calculate_interrupt_delay(struct ena_com_dev *ena_dev
if ((pkts > curr_moder_entry->pkts_per_interval) ||
(bytes > curr_moder_entry->bytes_per_interval))
new_moder_idx =
(enum ena_intr_moder_level)(curr_moder_idx + 1);
(enum ena_intr_moder_level)(curr_moder_idx + ENA_INTR_MODER_LEVEL_STRIDE);
} else {
pred_moder_entry = &intr_moder_tbl[curr_moder_idx - 1];
pred_moder_entry = &intr_moder_tbl[curr_moder_idx - ENA_INTR_MODER_LEVEL_STRIDE];
if ((pkts <= pred_moder_entry->pkts_per_interval) ||
(bytes <= pred_moder_entry->bytes_per_interval))
new_moder_idx =
(enum ena_intr_moder_level)(curr_moder_idx - 1);
(enum ena_intr_moder_level)(curr_moder_idx - ENA_INTR_MODER_LEVEL_STRIDE);
else if ((pkts > curr_moder_entry->pkts_per_interval) ||
(bytes > curr_moder_entry->bytes_per_interval)) {
if (curr_moder_idx != ENA_INTR_MODER_HIGHEST)
new_moder_idx =
(enum ena_intr_moder_level)(curr_moder_idx + 1);
(enum ena_intr_moder_level)(curr_moder_idx + ENA_INTR_MODER_LEVEL_STRIDE);
}
}
new_moder_entry = &intr_moder_tbl[new_moder_idx];
@@ -32,17 +32,13 @@
#ifndef _ENA_COMMON_H_
#define _ENA_COMMON_H_
/* spec version */
#define ENA_COMMON_SPEC_VERSION_MAJOR 0 /* spec version major */
#define ENA_COMMON_SPEC_VERSION_MINOR 10 /* spec version minor */
#define ENA_COMMON_SPEC_VERSION_MAJOR 0 /* */
#define ENA_COMMON_SPEC_VERSION_MINOR 10 /* */
/* ENA operates with 48-bit memory addresses. ena_mem_addr_t */
struct ena_common_mem_addr {
/* word 0 : low 32 bit of the memory address */
u32 mem_addr_low;
/* word 1 : */
/* high 16 bits of the memory address */
u16 mem_addr_high;
/* MBZ */
@@ -45,12 +45,13 @@ static inline struct ena_eth_io_rx_cdesc_base *ena_com_get_next_rx_cdesc(
cdesc = (struct ena_eth_io_rx_cdesc_base *)(io_cq->cdesc_addr.virt_addr
+ (head_masked * io_cq->cdesc_entry_size_in_bytes));
desc_phase = (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK) >>
desc_phase = (READ_ONCE(cdesc->status) & ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK) >>
ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT;
if (desc_phase != expected_phase)
return NULL;
return cdesc;
}
@@ -109,7 +110,7 @@ static inline int ena_com_write_header(struct ena_com_io_sq *io_sq,
return 0;
if (unlikely(!io_sq->header_addr)) {
ena_trc_err("Push buffer header ptr is NULL\n");
pr_err("Push buffer header ptr is NULL\n");
return -EINVAL;
}
@@ -141,7 +142,7 @@ static inline u16 ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq *io_cq,
ena_com_cq_inc_head(io_cq);
count++;
last = (cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK) >>
last = (READ_ONCE(cdesc->status) & ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK) >>
ENA_ETH_IO_RX_CDESC_BASE_LAST_SHIFT;
} while (!last);
@@ -154,8 +155,8 @@ static inline u16 ena_com_cdesc_rx_pkt_get(struct ena_com_io_cq *io_cq,
io_cq->cur_rx_pkt_cdesc_count = 0;
io_cq->cur_rx_pkt_cdesc_start_idx = head_masked;
ena_trc_dbg("ena q_id: %d packets were completed. first desc idx %u descs# %d\n",
io_cq->qid, *first_cdesc_idx, count);
pr_debug("ena q_id: %d packets were completed. first desc idx %u descs# %d\n",
io_cq->qid, *first_cdesc_idx, count);
} else {
io_cq->cur_rx_pkt_cdesc_count += count;
count = 0;
@@ -250,14 +251,10 @@ static inline void ena_com_rx_set_flags(struct ena_com_rx_ctx *ena_rx_ctx,
(cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK) >>
ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_SHIFT;
ena_trc_dbg("ena_rx_ctx->l3_proto %d ena_rx_ctx->l4_proto %d\nena_rx_ctx->l3_csum_err %d ena_rx_ctx->l4_csum_err %d\nhash frag %d frag: %d cdesc_status: %x\n",
ena_rx_ctx->l3_proto,
ena_rx_ctx->l4_proto,
ena_rx_ctx->l3_csum_err,
ena_rx_ctx->l4_csum_err,
ena_rx_ctx->hash,
ena_rx_ctx->frag,
cdesc->status);
pr_debug("ena_rx_ctx->l3_proto %d ena_rx_ctx->l4_proto %d\nena_rx_ctx->l3_csum_err %d ena_rx_ctx->l4_csum_err %d\nhash frag %d frag: %d cdesc_status: %x\n",
ena_rx_ctx->l3_proto, ena_rx_ctx->l4_proto,
ena_rx_ctx->l3_csum_err, ena_rx_ctx->l4_csum_err,
ena_rx_ctx->hash, ena_rx_ctx->frag, cdesc->status);
}
/*****************************************************************************/
@@ -277,18 +274,17 @@ int ena_com_prepare_tx(struct ena_com_io_sq *io_sq,
bool have_meta;
u64 addr_hi;
ENA_ASSERT(io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_TX,
"wrong Q type");
WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_TX, "wrong Q type");
/* num_bufs +1 for potential meta desc */
if (ena_com_sq_empty_space(io_sq) < (num_bufs + 1)) {
ena_trc_err("Not enough space in the tx queue\n");
pr_err("Not enough space in the tx queue\n");
return -ENOMEM;
}
if (unlikely(header_len > io_sq->tx_max_header_size)) {
ena_trc_err("header size is too large %d max header: %d\n",
header_len, io_sq->tx_max_header_size);
pr_err("header size is too large %d max header: %d\n",
header_len, io_sq->tx_max_header_size);
return -EINVAL;
}
@@ -407,21 +403,20 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
u16 nb_hw_desc;
u16 i;
ENA_ASSERT(io_cq->direction == ENA_COM_IO_QUEUE_DIRECTION_RX,
"wrong Q type");
WARN(io_cq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX, "wrong Q type");
nb_hw_desc = ena_com_cdesc_rx_pkt_get(io_cq, &cdesc_idx);
if (nb_hw_desc == 0) {
ena_rx_ctx->descs = nb_hw_desc;
return 0;
}
ena_trc_dbg("fetch rx packet: queue %d completed desc: %d\n",
io_cq->qid, nb_hw_desc);
pr_debug("fetch rx packet: queue %d completed desc: %d\n", io_cq->qid,
nb_hw_desc);
if (unlikely(nb_hw_desc > ena_rx_ctx->max_bufs)) {
ena_trc_err("Too many RX cdescs (%d) > MAX(%d)\n",
nb_hw_desc, ena_rx_ctx->max_bufs);
pr_err("Too many RX cdescs (%d) > MAX(%d)\n", nb_hw_desc,
ena_rx_ctx->max_bufs);
return -ENOSPC;
}
@@ -436,8 +431,8 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq,
/* Update SQ head ptr */
io_sq->next_to_comp += nb_hw_desc;
ena_trc_dbg("[%s][QID#%d] Updating SQ head to: %d\n", __func__,
io_sq->qid, io_sq->next_to_comp);
pr_debug("[%s][QID#%d] Updating SQ head to: %d\n", __func__, io_sq->qid,
io_sq->next_to_comp);
/* Get rx flags from the last pkt */
ena_com_rx_set_flags(ena_rx_ctx, cdesc);
@@ -452,8 +447,7 @@ int ena_com_add_single_rx_desc(struct ena_com_io_sq *io_sq,
{
struct ena_eth_io_rx_desc *desc;
ENA_ASSERT(io_sq->direction == ENA_COM_IO_QUEUE_DIRECTION_RX,
"wrong Q type");
WARN(io_sq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX, "wrong Q type");
if (unlikely(ena_com_sq_empty_space(io_sq) == 0))
return -ENOSPC;
@@ -496,13 +490,13 @@ int ena_com_tx_comp_req_id_get(struct ena_com_io_cq *io_cq, u16 *req_id)
* expected, it mean that the device still didn't update
* this completion.
*/
cdesc_phase = cdesc->flags & ENA_ETH_IO_TX_CDESC_PHASE_MASK;
cdesc_phase = READ_ONCE(cdesc->flags) & ENA_ETH_IO_TX_CDESC_PHASE_MASK;
if (cdesc_phase != expected_phase)
return -EAGAIN;
ena_com_cq_inc_head(io_cq);
*req_id = cdesc->req_id;
*req_id = READ_ONCE(cdesc->req_id);
return 0;
}
@@ -111,8 +111,8 @@ static inline int ena_com_write_sq_doorbell(struct ena_com_io_sq *io_sq)
tail = io_sq->tail;
ena_trc_dbg("write submission queue doorbell for queue: %d tail: %d\n",
io_sq->qid, tail);
pr_debug("write submission queue doorbell for queue: %d tail: %d\n",
io_sq->qid, tail);
writel(tail, io_sq->db_addr);
@@ -129,8 +129,8 @@ static inline int ena_com_update_dev_comp_head(struct ena_com_io_cq *io_cq)
need_update = unreported_comp > (io_cq->q_depth / ENA_COMP_HEAD_THRESH);
if (io_cq->cq_head_db_reg && need_update) {
ena_trc_dbg("Write completion queue doorbell for queue %d: head: %d\n",
io_cq->qid, head);
pr_debug("Write completion queue doorbell for queue %d: head: %d\n",
io_cq->qid, head);
writel(head, io_cq->cq_head_db_reg);
io_cq->last_head_update = head;
}
Oops, something went wrong.

0 comments on commit a485656

Please sign in to comment.