mirror of
https://github.com/opnsense/src.git
synced 2026-05-19 08:25:22 -04:00
ena: Remove redundant declaration of ena_log_level. GCC6 raises a -Wredundant-decl error due to duplicate declarations in ena_fbsd_log.h and ena_plat.h. Sponsored by: Chelsio Communications (cherry picked from commit8843787aa1) ena: Avoid unnecessary mbuf collapses for LLQ condition In case of Low-latency Queue, one small enough descriptor can be pushed directly to the ENA hw, thus saving one fragment. Check for this condition before performing collapse. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commitc81f8c2611) ena: Trigger reset on ena_com_prepare_tx failure All ena_com_prepare_tx errors other than ENA_COM_NO_MEM are fatal and require device reset. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit36130d2979) ena: Prevent reset after device destruction Check for ENA_FLAG_TRIGGER_RESET inside a locked context in order to avoid potential race conditions with ena_destroy_device. This aligns the reset task logic with the Linux driver. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit433ab9b698) ena: Add extra log messages Stay aligned with the Linux driver by adding the following logs: * inform the user about retrying queue creation * warn on non-empty ena_tx_buffer.mbuf prior to ena_tx_map_mbuf Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit77160654a1) ena: Add locking assertions ENA silently assumed that ena_up, ena_down and ena_start_xmit routines should be called within locked context. Driver's logic heavily assumes on concurrent access to those routines, so for safety and better documentation about this assumption, the locking assertions were added to the above functions. The assertion was added only for the main steps (skipping the helper functions) which can be called from multiple places including the kernel and the driver itself. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commitcb98c439d6) ena: Move RSS logic into its own source files Delegate RSS related functionality into separate .c/.h files in preparation for the full RSS support. While at it, reorder functions and remove prototypes for ones with internal linkage. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit986e7b9227) ena: Disable meta descriptor caching for netmap If LLQ is being used, `ena_tx_ctx.meta_valid` must stay enabled. This fixes netmap support on latest generation ENA HW and aligns it with the core driver behavior. As netmap doesn't support any csum offloads, the `adapter->disable_meta_caching` value can be simply passed to the HW. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commita831466830) ena: Share ena_global_lock between driver instances In order to use `ena_global_lock` in sysctl context, it must be kept outside the driver instance's software context, as sysctls can be called before attach and after detach, leading to lock use before sx_init and after sx_destroy otherwise. Solve this issue by turning `ena_global_lock` into a file scope variable, shared between all instances of the driver and associated sysctl context, and in turn initialized/destroyed in dedicated SYSINIT/SYSUNINIT functions. As a side effect, this change also fixes existing race in the reset routine, when simultaneously accessing sysctl exposed properties. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit07aff471c0) ena: Add missing statistics Provide the following sysctl statistics in order to stay aligned with the Linux driver: * rx_ring.csum_good * tx_ring.unmask_interrupt_num Also rename the 'bad_csum' statistic name to 'csum_bad' for alignment. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit223c8cb12e) ena: Implement full RSS reconfiguration Bind RX/TX queues and MSI-X vectors to matching CPUs based on the RSS bucket entries. Introduce sysctls for the following RSS functionality: - rss.indir_table: indirection table mapping - rss.indir_table_size: indirection table size - rss.key: RSS hash key (if Toeplitz used) Said sysctls are only available when compiled without `option RSS`, as kernel-side RSS support currently doesn't offer RSS reconfiguration. Migrate the hash algorithm from CRC32 to Toeplitz and change the initial hash value to 0x0 in order to match the standard Toeplitz implementation. Provide helpers for hash key inversion required for HW operations. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit6d1ef2abd3) ena: fix building in-kernel driver When building ENA as compiled into the kernel, the driver would fail to build. Resolve the problem by introducing the following changes: 1. Add missing `ena_rss.c` entry in `sys/conf/files`. 2. Prevent SYSCTL_ADD_INT from throwing an assert due to an extra CTLTYPE_INT flag. Fixes:986e7b9227("ena: Move RSS logic into its own source files") Fixes:6d1ef2abd3("ena: Implement full RSS reconfiguration") Obtained from: Semihalf Sponsored by: Amazon, Inc. MFC after: 1 week (cherry picked from commita3f0d18237) ena: Update driver version to v2.4.1 Some of the changes in this release: * Hardware RSS hash key reconfiguration and indirection table reconfiguration support. * Full kernel RSS support. * Extra statistic counters. * Netmap support for ENAv3. * Locking assertions. * Extra log messages. * Reset handling fixes. Obtained from: Semihalf MFC after: 2 weeks Sponsored by: Amazon, Inc. (cherry picked from commit42c7760be3)
300 lines
7.6 KiB
C
300 lines
7.6 KiB
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2015-2021 Amazon.com, Inc. or its affiliates.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include "opt_rss.h"
|
|
|
|
#include "ena_rss.h"
|
|
|
|
/*
|
|
* This function should generate unique key for the whole driver.
|
|
* If the key was already genereated in the previous call (for example
|
|
* for another adapter), then it should be returned instead.
|
|
*/
|
|
void
|
|
ena_rss_key_fill(void *key, size_t size)
|
|
{
|
|
static bool key_generated;
|
|
static uint8_t default_key[ENA_HASH_KEY_SIZE];
|
|
|
|
KASSERT(size <= ENA_HASH_KEY_SIZE, ("Requested more bytes than ENA RSS key can hold"));
|
|
|
|
if (!key_generated) {
|
|
arc4random_buf(default_key, ENA_HASH_KEY_SIZE);
|
|
key_generated = true;
|
|
}
|
|
|
|
memcpy(key, default_key, size);
|
|
}
|
|
|
|
/*
|
|
* ENA HW expects the key to be in reverse-byte order.
|
|
*/
|
|
static void
|
|
ena_rss_reorder_hash_key(u8 *reordered_key, const u8 *key, size_t key_size)
|
|
{
|
|
int i;
|
|
|
|
key = key + key_size - 1;
|
|
|
|
for (i = 0; i < key_size; ++i)
|
|
*reordered_key++ = *key--;
|
|
}
|
|
|
|
int ena_rss_set_hash(struct ena_com_dev *ena_dev, const u8 *key)
|
|
{
|
|
enum ena_admin_hash_functions ena_func = ENA_ADMIN_TOEPLITZ;
|
|
u8 hw_key[ENA_HASH_KEY_SIZE];
|
|
|
|
ena_rss_reorder_hash_key(hw_key, key, ENA_HASH_KEY_SIZE);
|
|
|
|
return (ena_com_fill_hash_function(ena_dev, ena_func, hw_key,
|
|
ENA_HASH_KEY_SIZE, 0x0));
|
|
}
|
|
|
|
int ena_rss_get_hash_key(struct ena_com_dev *ena_dev, u8 *key)
|
|
{
|
|
u8 hw_key[ENA_HASH_KEY_SIZE];
|
|
int rc;
|
|
|
|
rc = ena_com_get_hash_key(ena_dev, hw_key);
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
ena_rss_reorder_hash_key(key, hw_key, ENA_HASH_KEY_SIZE);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
ena_rss_init_default(struct ena_adapter *adapter)
|
|
{
|
|
struct ena_com_dev *ena_dev = adapter->ena_dev;
|
|
device_t dev = adapter->pdev;
|
|
int qid, rc, i;
|
|
|
|
rc = ena_com_rss_init(ena_dev, ENA_RX_RSS_TABLE_LOG_SIZE);
|
|
if (unlikely(rc != 0)) {
|
|
ena_log(dev, ERR, "Cannot init indirect table\n");
|
|
return (rc);
|
|
}
|
|
|
|
for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {
|
|
#ifdef RSS
|
|
qid = rss_get_indirection_to_bucket(i) % adapter->num_io_queues;
|
|
#else
|
|
qid = i % adapter->num_io_queues;
|
|
#endif
|
|
rc = ena_com_indirect_table_fill_entry(ena_dev, i,
|
|
ENA_IO_RXQ_IDX(qid));
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP))) {
|
|
ena_log(dev, ERR, "Cannot fill indirect table\n");
|
|
goto err_rss_destroy;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef RSS
|
|
uint8_t rss_algo = rss_gethashalgo();
|
|
if (rss_algo == RSS_HASH_TOEPLITZ) {
|
|
uint8_t hash_key[RSS_KEYSIZE];
|
|
|
|
rss_getkey(hash_key);
|
|
rc = ena_rss_set_hash(ena_dev, hash_key);
|
|
} else
|
|
#endif
|
|
rc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_TOEPLITZ, NULL,
|
|
ENA_HASH_KEY_SIZE, 0x0);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP))) {
|
|
ena_log(dev, ERR, "Cannot fill hash function\n");
|
|
goto err_rss_destroy;
|
|
}
|
|
|
|
rc = ena_com_set_default_hash_ctrl(ena_dev);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP))) {
|
|
ena_log(dev, ERR, "Cannot fill hash control\n");
|
|
goto err_rss_destroy;
|
|
}
|
|
|
|
rc = ena_rss_indir_init(adapter);
|
|
|
|
return (rc == EOPNOTSUPP ? 0 : rc);
|
|
|
|
err_rss_destroy:
|
|
ena_com_rss_destroy(ena_dev);
|
|
return (rc);
|
|
}
|
|
|
|
/* Configure the Rx forwarding */
|
|
int
|
|
ena_rss_configure(struct ena_adapter *adapter)
|
|
{
|
|
struct ena_com_dev *ena_dev = adapter->ena_dev;
|
|
int rc;
|
|
|
|
/* In case the RSS table was destroyed */
|
|
if (!ena_dev->rss.tbl_log_size) {
|
|
rc = ena_rss_init_default(adapter);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP))) {
|
|
ena_log(adapter->pdev, ERR,
|
|
"WARNING: RSS was not properly re-initialized,"
|
|
" it will affect bandwidth\n");
|
|
ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_RSS_ACTIVE, adapter);
|
|
return (rc);
|
|
}
|
|
}
|
|
|
|
/* Set indirect table */
|
|
rc = ena_com_indirect_table_set(ena_dev);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP)))
|
|
return (rc);
|
|
|
|
/* Configure hash function (if supported) */
|
|
rc = ena_com_set_hash_function(ena_dev);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP)))
|
|
return (rc);
|
|
|
|
/* Configure hash inputs (if supported) */
|
|
rc = ena_com_set_hash_ctrl(ena_dev);
|
|
if (unlikely((rc != 0) && (rc != EOPNOTSUPP)))
|
|
return (rc);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static void
|
|
ena_rss_init_default_deferred(void *arg)
|
|
{
|
|
struct ena_adapter *adapter;
|
|
devclass_t dc;
|
|
int max;
|
|
int rc;
|
|
|
|
dc = devclass_find("ena");
|
|
if (unlikely(dc == NULL)) {
|
|
ena_log_raw(ERR, "SYSINIT: %s: No devclass ena\n", __func__);
|
|
return;
|
|
}
|
|
|
|
max = devclass_get_maxunit(dc);
|
|
while (max-- >= 0) {
|
|
adapter = devclass_get_softc(dc, max);
|
|
if (adapter != NULL) {
|
|
rc = ena_rss_init_default(adapter);
|
|
ENA_FLAG_SET_ATOMIC(ENA_FLAG_RSS_ACTIVE, adapter);
|
|
if (unlikely(rc != 0)) {
|
|
ena_log(adapter->pdev, WARN,
|
|
"WARNING: RSS was not properly initialized,"
|
|
" it will affect bandwidth\n");
|
|
ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_RSS_ACTIVE, adapter);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SYSINIT(ena_rss_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_SECOND, ena_rss_init_default_deferred, NULL);
|
|
|
|
int
|
|
ena_rss_indir_get(struct ena_adapter *adapter, uint32_t *table)
|
|
{
|
|
int rc, i;
|
|
|
|
rc = ena_com_indirect_table_get(adapter->ena_dev, table);
|
|
if (rc != 0) {
|
|
if (rc == EOPNOTSUPP)
|
|
device_printf(adapter->pdev,
|
|
"Reading from indirection table not supported\n");
|
|
else
|
|
device_printf(adapter->pdev,
|
|
"Unable to get indirection table\n");
|
|
return (rc);
|
|
}
|
|
|
|
for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; ++i)
|
|
table[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(table[i]);
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
ena_rss_indir_set(struct ena_adapter *adapter, uint32_t *table)
|
|
{
|
|
int rc, i;
|
|
|
|
for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; ++i) {
|
|
rc = ena_com_indirect_table_fill_entry(adapter->ena_dev, i,
|
|
ENA_IO_RXQ_IDX(table[i]));
|
|
if (rc != 0) {
|
|
device_printf(adapter->pdev,
|
|
"Cannot fill indirection table entry %d\n", i);
|
|
return (rc);
|
|
}
|
|
}
|
|
|
|
rc = ena_com_indirect_table_set(adapter->ena_dev);
|
|
if (rc == EOPNOTSUPP)
|
|
device_printf(adapter->pdev,
|
|
"Writing to indirection table not supported\n");
|
|
else if (rc != 0)
|
|
device_printf(adapter->pdev,
|
|
"Cannot set indirection table\n");
|
|
|
|
return (rc);
|
|
}
|
|
|
|
int
|
|
ena_rss_indir_init(struct ena_adapter *adapter)
|
|
{
|
|
struct ena_indir *indir = adapter->rss_indir;
|
|
int rc;
|
|
|
|
if (indir == NULL) {
|
|
adapter->rss_indir = indir = malloc(sizeof(struct ena_indir),
|
|
M_DEVBUF, M_WAITOK | M_ZERO);
|
|
if (indir == NULL)
|
|
return (ENOMEM);
|
|
}
|
|
|
|
rc = ena_rss_indir_get(adapter, indir->table);
|
|
if (rc != 0) {
|
|
free(adapter->rss_indir, M_DEVBUF);
|
|
adapter->rss_indir = NULL;
|
|
|
|
return (rc);
|
|
}
|
|
|
|
ena_rss_copy_indir_buf(indir->sysctl_buf, indir->table);
|
|
|
|
return (0);
|
|
}
|