From owner-dev-commits-src-all@freebsd.org Thu Jun 24 14:35:52 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E4AF864D688; Thu, 24 Jun 2021 14:35:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4G9jNm4YbPz4c8D; Thu, 24 Jun 2021 14:35:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 63C6019BC2; Thu, 24 Jun 2021 14:35:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 15OEZqVP032516; Thu, 24 Jun 2021 14:35:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 15OEZqmR032514; Thu, 24 Jun 2021 14:35:52 GMT (envelope-from git) Date: Thu, 24 Jun 2021 14:35:52 GMT Message-Id: <202106241435.15OEZqmR032514@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Marcin Wojtas Subject: git: 3fc5d816f883 - main - Merge tag 'vendor/ena-com/2.4.0' MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mw X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3fc5d816f8831d6fc2816ac97bd78dc486cd080c Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Jun 2021 14:35:53 -0000 The branch main has been updated by mw: URL: https://cgit.FreeBSD.org/src/commit/?id=3fc5d816f8831d6fc2816ac97bd78dc486cd080c commit 3fc5d816f8831d6fc2816ac97bd78dc486cd080c Merge: 0e7d31f63b9d 1f4f67f52424 Author: Marcin Wojtas AuthorDate: 2021-06-24 14:07:33 +0000 Commit: Marcin Wojtas CommitDate: 2021-06-24 14:15:18 +0000 Merge tag 'vendor/ena-com/2.4.0' Update the driver in order not to break its compilation and make use of the new ENA logging system Migrate platform code to the new logging system provided by ena_com layer. Make ENA_INFO the new default log level. Remove all explicit use of `device_printf`, all new logs requiring one of the log macros to be used. sys/contrib/ena-com/ena_com.c | 37 +-- sys/contrib/ena-com/ena_com.h | 6 +- sys/contrib/ena-com/ena_defs/ena_admin_defs.h | 23 +- sys/contrib/ena-com/ena_defs/ena_gen_info.h | 6 +- sys/contrib/ena-com/ena_eth_com.c | 4 +- sys/contrib/ena-com/ena_fbsd_log.h | 74 ++++++ sys/contrib/ena-com/ena_plat.h | 37 +-- sys/dev/ena/ena.c | 342 +++++++++++++------------- sys/dev/ena/ena_datapath.c | 83 ++++--- sys/dev/ena/ena_netmap.c | 73 +++--- sys/dev/ena/ena_sysctl.c | 30 +-- 11 files changed, 397 insertions(+), 318 deletions(-) diff --cc sys/contrib/ena-com/ena_fbsd_log.h index 000000000000,311e2f0f280a..311e2f0f280a mode 000000,100644..100644 --- a/sys/contrib/ena-com/ena_fbsd_log.h +++ b/sys/contrib/ena-com/ena_fbsd_log.h diff --cc sys/dev/ena/ena.c index fbe32a7a930e,000000000000..84d58c844332 mode 100644,000000..100644 --- a/sys/dev/ena/ena.c +++ b/sys/dev/ena/ena.c @@@ -1,3980 -1,0 +1,3984 @@@ +/*- + * 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. + */ +#include +__FBSDID("$FreeBSD$"); + +#include "opt_rss.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef RSS +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "ena_datapath.h" +#include "ena.h" +#include "ena_sysctl.h" + +#ifdef DEV_NETMAP +#include "ena_netmap.h" +#endif /* DEV_NETMAP */ + +/********************************************************* + * Function prototypes + *********************************************************/ +static int ena_probe(device_t); +static void ena_intr_msix_mgmnt(void *); +static void ena_free_pci_resources(struct ena_adapter *); +static int ena_change_mtu(if_t, int); +static inline void ena_alloc_counters(counter_u64_t *, int); +static inline void ena_free_counters(counter_u64_t *, int); +static inline void ena_reset_counters(counter_u64_t *, int); +static void ena_init_io_rings_common(struct ena_adapter *, + struct ena_ring *, uint16_t); +static void ena_init_io_rings_basic(struct ena_adapter *); +static void ena_init_io_rings_advanced(struct ena_adapter *); +static void ena_init_io_rings(struct ena_adapter *); +static void ena_free_io_ring_resources(struct ena_adapter *, unsigned int); +static void ena_free_all_io_rings_resources(struct ena_adapter *); +static int ena_setup_tx_dma_tag(struct ena_adapter *); +static int ena_free_tx_dma_tag(struct ena_adapter *); +static int ena_setup_rx_dma_tag(struct ena_adapter *); +static int ena_free_rx_dma_tag(struct ena_adapter *); +static void ena_release_all_tx_dmamap(struct ena_ring *); +static int ena_setup_tx_resources(struct ena_adapter *, int); +static void ena_free_tx_resources(struct ena_adapter *, int); +static int ena_setup_all_tx_resources(struct ena_adapter *); +static void ena_free_all_tx_resources(struct ena_adapter *); +static int ena_setup_rx_resources(struct ena_adapter *, unsigned int); +static void ena_free_rx_resources(struct ena_adapter *, unsigned int); +static int ena_setup_all_rx_resources(struct ena_adapter *); +static void ena_free_all_rx_resources(struct ena_adapter *); +static inline int ena_alloc_rx_mbuf(struct ena_adapter *, struct ena_ring *, + struct ena_rx_buffer *); +static void ena_free_rx_mbuf(struct ena_adapter *, struct ena_ring *, + struct ena_rx_buffer *); +static void ena_free_rx_bufs(struct ena_adapter *, unsigned int); +static void ena_refill_all_rx_bufs(struct ena_adapter *); +static void ena_free_all_rx_bufs(struct ena_adapter *); +static void ena_free_tx_bufs(struct ena_adapter *, unsigned int); +static void ena_free_all_tx_bufs(struct ena_adapter *); +static void ena_destroy_all_tx_queues(struct ena_adapter *); +static void ena_destroy_all_rx_queues(struct ena_adapter *); +static void ena_destroy_all_io_queues(struct ena_adapter *); +static int ena_create_io_queues(struct ena_adapter *); +static int ena_handle_msix(void *); +static int ena_enable_msix(struct ena_adapter *); +static void ena_setup_mgmnt_intr(struct ena_adapter *); +static int ena_setup_io_intr(struct ena_adapter *); +static int ena_request_mgmnt_irq(struct ena_adapter *); +static int ena_request_io_irq(struct ena_adapter *); +static void ena_free_mgmnt_irq(struct ena_adapter *); +static void ena_free_io_irq(struct ena_adapter *); +static void ena_free_irqs(struct ena_adapter*); +static void ena_disable_msix(struct ena_adapter *); +static void ena_unmask_all_io_irqs(struct ena_adapter *); +static int ena_rss_configure(struct ena_adapter *); +static int ena_up_complete(struct ena_adapter *); +static uint64_t ena_get_counter(if_t, ift_counter); +static int ena_media_change(if_t); +static void ena_media_status(if_t, struct ifmediareq *); +static void ena_init(void *); +static int ena_ioctl(if_t, u_long, caddr_t); +static int ena_get_dev_offloads(struct ena_com_dev_get_features_ctx *); +static void ena_update_host_info(struct ena_admin_host_info *, if_t); +static void ena_update_hwassist(struct ena_adapter *); +static int ena_setup_ifnet(device_t, struct ena_adapter *, + struct ena_com_dev_get_features_ctx *); - static int ena_enable_wc(struct resource *); ++static int ena_enable_wc(device_t, struct resource *); +static int ena_set_queues_placement_policy(device_t, struct ena_com_dev *, + struct ena_admin_feature_llq_desc *, struct ena_llq_configurations *); +static uint32_t ena_calc_max_io_queue_num(device_t, struct ena_com_dev *, + struct ena_com_dev_get_features_ctx *); +static int ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *); +static int ena_rss_init_default(struct ena_adapter *); +static void ena_rss_init_default_deferred(void *); +static void ena_config_host_info(struct ena_com_dev *, device_t); +static int ena_attach(device_t); +static int ena_detach(device_t); +static int ena_device_init(struct ena_adapter *, device_t, + struct ena_com_dev_get_features_ctx *, int *); +static int ena_enable_msix_and_set_admin_interrupts(struct ena_adapter *); +static void ena_update_on_link_change(void *, struct ena_admin_aenq_entry *); +static void unimplemented_aenq_handler(void *, + struct ena_admin_aenq_entry *); +static int ena_copy_eni_metrics(struct ena_adapter *); +static void ena_timer_service(void *); + +static char ena_version[] = DEVICE_NAME DRV_MODULE_NAME " v" DRV_MODULE_VERSION; + +static ena_vendor_info_t ena_vendor_info_array[] = { + { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_PF, 0}, + { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_PF_RSERV0, 0}, + { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_VF, 0}, + { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_VF_RSERV0, 0}, + /* Last entry */ + { 0, 0, 0 } +}; + +/* + * Contains pointers to event handlers, e.g. link state chage. + */ +static struct ena_aenq_handlers aenq_handlers; + +void +ena_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + if (error != 0) + return; + *(bus_addr_t *) arg = segs[0].ds_addr; +} + +int +ena_dma_alloc(device_t dmadev, bus_size_t size, + ena_mem_handle_t *dma, int mapflags, bus_size_t alignment) +{ + struct ena_adapter* adapter = device_get_softc(dmadev); ++ device_t pdev = adapter->pdev; + uint32_t maxsize; + uint64_t dma_space_addr; + int error; + + maxsize = ((size - 1) / PAGE_SIZE + 1) * PAGE_SIZE; + + dma_space_addr = ENA_DMA_BIT_MASK(adapter->dma_width); + if (unlikely(dma_space_addr == 0)) + dma_space_addr = BUS_SPACE_MAXADDR; + + error = bus_dma_tag_create(bus_get_dma_tag(dmadev), /* parent */ + alignment, 0, /* alignment, bounds */ + dma_space_addr, /* lowaddr of exclusion window */ + BUS_SPACE_MAXADDR,/* highaddr of exclusion window */ + NULL, NULL, /* filter, filterarg */ + maxsize, /* maxsize */ + 1, /* nsegments */ + maxsize, /* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + NULL, /* lockfunc */ + NULL, /* lockarg */ + &dma->tag); + if (unlikely(error != 0)) { - ena_trace(NULL, ENA_ALERT, "bus_dma_tag_create failed: %d\n", error); ++ ena_log(pdev, ERR, "bus_dma_tag_create failed: %d\n", error); + goto fail_tag; + } + + error = bus_dmamem_alloc(dma->tag, (void**) &dma->vaddr, + BUS_DMA_COHERENT | BUS_DMA_ZERO, &dma->map); + if (unlikely(error != 0)) { - ena_trace(NULL, ENA_ALERT, "bus_dmamem_alloc(%ju) failed: %d\n", ++ ena_log(pdev, ERR, "bus_dmamem_alloc(%ju) failed: %d\n", + (uintmax_t)size, error); + goto fail_map_create; + } + + dma->paddr = 0; + error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, + size, ena_dmamap_callback, &dma->paddr, mapflags); + if (unlikely((error != 0) || (dma->paddr == 0))) { - ena_trace(NULL, ENA_ALERT, ": bus_dmamap_load failed: %d\n", error); ++ ena_log(pdev, ERR, "bus_dmamap_load failed: %d\n", error); + goto fail_map_load; + } + + bus_dmamap_sync(dma->tag, dma->map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + return (0); + +fail_map_load: + bus_dmamem_free(dma->tag, dma->vaddr, dma->map); +fail_map_create: + bus_dma_tag_destroy(dma->tag); +fail_tag: + dma->tag = NULL; + dma->vaddr = NULL; + dma->paddr = 0; + + return (error); +} + +/* + * 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); +} + +static void +ena_free_pci_resources(struct ena_adapter *adapter) +{ + device_t pdev = adapter->pdev; + + if (adapter->memory != NULL) { + bus_release_resource(pdev, SYS_RES_MEMORY, + PCIR_BAR(ENA_MEM_BAR), adapter->memory); + } + + if (adapter->registers != NULL) { + bus_release_resource(pdev, SYS_RES_MEMORY, + PCIR_BAR(ENA_REG_BAR), adapter->registers); + } + + if (adapter->msix != NULL) { + bus_release_resource(pdev, SYS_RES_MEMORY, + adapter->msix_rid, adapter->msix); + } +} + +static int +ena_probe(device_t dev) +{ + ena_vendor_info_t *ent; + char adapter_name[60]; + uint16_t pci_vendor_id = 0; + uint16_t pci_device_id = 0; + + pci_vendor_id = pci_get_vendor(dev); + pci_device_id = pci_get_device(dev); + + ent = ena_vendor_info_array; + while (ent->vendor_id != 0) { + if ((pci_vendor_id == ent->vendor_id) && + (pci_device_id == ent->device_id)) { - ena_trace(NULL, ENA_DBG, "vendor=%x device=%x\n", ++ ena_log_raw(DBG, "vendor=%x device=%x\n", + pci_vendor_id, pci_device_id); + + sprintf(adapter_name, DEVICE_DESC); + device_set_desc_copy(dev, adapter_name); + return (BUS_PROBE_DEFAULT); + } + + ent++; + + } + + return (ENXIO); +} + +static int +ena_change_mtu(if_t ifp, int new_mtu) +{ + struct ena_adapter *adapter = if_getsoftc(ifp); ++ device_t pdev = adapter->pdev; + int rc; + + if ((new_mtu > adapter->max_mtu) || (new_mtu < ENA_MIN_MTU)) { - device_printf(adapter->pdev, "Invalid MTU setting. " ++ ena_log(pdev, ERR, "Invalid MTU setting. " + "new_mtu: %d max mtu: %d min mtu: %d\n", + new_mtu, adapter->max_mtu, ENA_MIN_MTU); + return (EINVAL); + } + + rc = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu); + if (likely(rc == 0)) { - ena_trace(NULL, ENA_DBG, "set MTU to %d\n", new_mtu); ++ ena_log(pdev, DBG, "set MTU to %d\n", new_mtu); + if_setmtu(ifp, new_mtu); + } else { - device_printf(adapter->pdev, "Failed to set MTU to %d\n", - new_mtu); ++ ena_log(pdev, ERR, "Failed to set MTU to %d\n", new_mtu); + } + + return (rc); +} + +static inline void +ena_alloc_counters(counter_u64_t *begin, int size) +{ + counter_u64_t *end = (counter_u64_t *)((char *)begin + size); + + for (; begin < end; ++begin) + *begin = counter_u64_alloc(M_WAITOK); +} + +static inline void +ena_free_counters(counter_u64_t *begin, int size) +{ + counter_u64_t *end = (counter_u64_t *)((char *)begin + size); + + for (; begin < end; ++begin) + counter_u64_free(*begin); +} + +static inline void +ena_reset_counters(counter_u64_t *begin, int size) +{ + counter_u64_t *end = (counter_u64_t *)((char *)begin + size); + + for (; begin < end; ++begin) + counter_u64_zero(*begin); +} + +static void +ena_init_io_rings_common(struct ena_adapter *adapter, struct ena_ring *ring, + uint16_t qid) +{ + + ring->qid = qid; + ring->adapter = adapter; + ring->ena_dev = adapter->ena_dev; + ring->first_interrupt = false; + ring->no_interrupt_event_cnt = 0; +} + +static void +ena_init_io_rings_basic(struct ena_adapter *adapter) +{ + struct ena_com_dev *ena_dev; + struct ena_ring *txr, *rxr; + struct ena_que *que; + int i; + + ena_dev = adapter->ena_dev; + + for (i = 0; i < adapter->num_io_queues; i++) { + txr = &adapter->tx_ring[i]; + rxr = &adapter->rx_ring[i]; + + /* TX/RX common ring state */ + ena_init_io_rings_common(adapter, txr, i); + ena_init_io_rings_common(adapter, rxr, i); + + /* TX specific ring state */ + txr->tx_max_header_size = ena_dev->tx_max_header_size; + txr->tx_mem_queue_type = ena_dev->tx_mem_queue_type; + + que = &adapter->que[i]; + que->adapter = adapter; + que->id = i; + que->tx_ring = txr; + que->rx_ring = rxr; + + txr->que = que; + rxr->que = que; + + rxr->empty_rx_queue = 0; + rxr->rx_mbuf_sz = ena_mbuf_sz; + } +} + +static void +ena_init_io_rings_advanced(struct ena_adapter *adapter) +{ + struct ena_ring *txr, *rxr; + int i; + + for (i = 0; i < adapter->num_io_queues; i++) { + txr = &adapter->tx_ring[i]; + rxr = &adapter->rx_ring[i]; + + /* Allocate a buf ring */ + txr->buf_ring_size = adapter->buf_ring_size; + txr->br = buf_ring_alloc(txr->buf_ring_size, M_DEVBUF, + M_WAITOK, &txr->ring_mtx); + + /* Allocate Tx statistics. */ + ena_alloc_counters((counter_u64_t *)&txr->tx_stats, + sizeof(txr->tx_stats)); + + /* Allocate Rx statistics. */ + ena_alloc_counters((counter_u64_t *)&rxr->rx_stats, + sizeof(rxr->rx_stats)); + + /* Initialize locks */ + snprintf(txr->mtx_name, nitems(txr->mtx_name), "%s:tx(%d)", + device_get_nameunit(adapter->pdev), i); + snprintf(rxr->mtx_name, nitems(rxr->mtx_name), "%s:rx(%d)", + device_get_nameunit(adapter->pdev), i); + + mtx_init(&txr->ring_mtx, txr->mtx_name, NULL, MTX_DEF); + } +} + +static void +ena_init_io_rings(struct ena_adapter *adapter) +{ + /* + * IO rings initialization can be divided into the 2 steps: + * 1. Initialize variables and fields with initial values and copy + * them from adapter/ena_dev (basic) + * 2. Allocate mutex, counters and buf_ring (advanced) + */ + ena_init_io_rings_basic(adapter); + ena_init_io_rings_advanced(adapter); +} + +static void +ena_free_io_ring_resources(struct ena_adapter *adapter, unsigned int qid) +{ + struct ena_ring *txr = &adapter->tx_ring[qid]; + struct ena_ring *rxr = &adapter->rx_ring[qid]; + + ena_free_counters((counter_u64_t *)&txr->tx_stats, + sizeof(txr->tx_stats)); + ena_free_counters((counter_u64_t *)&rxr->rx_stats, + sizeof(rxr->rx_stats)); + + ENA_RING_MTX_LOCK(txr); + drbr_free(txr->br, M_DEVBUF); + ENA_RING_MTX_UNLOCK(txr); + + mtx_destroy(&txr->ring_mtx); +} + +static void +ena_free_all_io_rings_resources(struct ena_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_io_queues; i++) + ena_free_io_ring_resources(adapter, i); + +} + +static int +ena_setup_tx_dma_tag(struct ena_adapter *adapter) +{ + int ret; + + /* Create DMA tag for Tx buffers */ + ret = bus_dma_tag_create(bus_get_dma_tag(adapter->pdev), + 1, 0, /* alignment, bounds */ + ENA_DMA_BIT_MASK(adapter->dma_width), /* lowaddr of excl window */ + BUS_SPACE_MAXADDR, /* highaddr of excl window */ + NULL, NULL, /* filter, filterarg */ + ENA_TSO_MAXSIZE, /* maxsize */ + adapter->max_tx_sgl_size - 1, /* nsegments */ + ENA_TSO_MAXSIZE, /* maxsegsize */ + 0, /* flags */ + NULL, /* lockfunc */ + NULL, /* lockfuncarg */ + &adapter->tx_buf_tag); + + return (ret); +} + +static int +ena_free_tx_dma_tag(struct ena_adapter *adapter) +{ + int ret; + + ret = bus_dma_tag_destroy(adapter->tx_buf_tag); + + if (likely(ret == 0)) + adapter->tx_buf_tag = NULL; + + return (ret); +} + +static int +ena_setup_rx_dma_tag(struct ena_adapter *adapter) +{ + int ret; + + /* Create DMA tag for Rx buffers*/ + ret = bus_dma_tag_create(bus_get_dma_tag(adapter->pdev), /* parent */ + 1, 0, /* alignment, bounds */ + ENA_DMA_BIT_MASK(adapter->dma_width), /* lowaddr of excl window */ + BUS_SPACE_MAXADDR, /* highaddr of excl window */ + NULL, NULL, /* filter, filterarg */ + ena_mbuf_sz, /* maxsize */ + adapter->max_rx_sgl_size, /* nsegments */ + ena_mbuf_sz, /* maxsegsize */ + 0, /* flags */ + NULL, /* lockfunc */ + NULL, /* lockarg */ + &adapter->rx_buf_tag); + + return (ret); +} + +static int +ena_free_rx_dma_tag(struct ena_adapter *adapter) +{ + int ret; + + ret = bus_dma_tag_destroy(adapter->rx_buf_tag); + + if (likely(ret == 0)) + adapter->rx_buf_tag = NULL; + + return (ret); +} + +static void +ena_release_all_tx_dmamap(struct ena_ring *tx_ring) +{ + struct ena_adapter *adapter = tx_ring->adapter; + struct ena_tx_buffer *tx_info; + bus_dma_tag_t tx_tag = adapter->tx_buf_tag;; + int i; +#ifdef DEV_NETMAP + struct ena_netmap_tx_info *nm_info; + int j; +#endif /* DEV_NETMAP */ + + for (i = 0; i < tx_ring->ring_size; ++i) { + tx_info = &tx_ring->tx_buffer_info[i]; +#ifdef DEV_NETMAP + if (adapter->ifp->if_capenable & IFCAP_NETMAP) { + nm_info = &tx_info->nm_info; + for (j = 0; j < ENA_PKT_MAX_BUFS; ++j) { + if (nm_info->map_seg[j] != NULL) { + bus_dmamap_destroy(tx_tag, + nm_info->map_seg[j]); + nm_info->map_seg[j] = NULL; + } + } + } +#endif /* DEV_NETMAP */ + if (tx_info->dmamap != NULL) { + bus_dmamap_destroy(tx_tag, tx_info->dmamap); + tx_info->dmamap = NULL; + } + } +} + +/** + * ena_setup_tx_resources - allocate Tx resources (Descriptors) + * @adapter: network interface device structure + * @qid: queue index + * + * Returns 0 on success, otherwise on failure. + **/ +static int +ena_setup_tx_resources(struct ena_adapter *adapter, int qid) +{ ++ device_t pdev = adapter->pdev; + struct ena_que *que = &adapter->que[qid]; + struct ena_ring *tx_ring = que->tx_ring; + int size, i, err; +#ifdef DEV_NETMAP + bus_dmamap_t *map; + int j; + + ena_netmap_reset_tx_ring(adapter, qid); +#endif /* DEV_NETMAP */ + + size = sizeof(struct ena_tx_buffer) * tx_ring->ring_size; + + tx_ring->tx_buffer_info = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); + if (unlikely(tx_ring->tx_buffer_info == NULL)) + return (ENOMEM); + + size = sizeof(uint16_t) * tx_ring->ring_size; + tx_ring->free_tx_ids = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); + if (unlikely(tx_ring->free_tx_ids == NULL)) + goto err_buf_info_free; + + size = tx_ring->tx_max_header_size; + tx_ring->push_buf_intermediate_buf = malloc(size, M_DEVBUF, + M_NOWAIT | M_ZERO); + if (unlikely(tx_ring->push_buf_intermediate_buf == NULL)) + goto err_tx_ids_free; + + /* Req id stack for TX OOO completions */ + for (i = 0; i < tx_ring->ring_size; i++) + tx_ring->free_tx_ids[i] = i; + + /* Reset TX statistics. */ + ena_reset_counters((counter_u64_t *)&tx_ring->tx_stats, + sizeof(tx_ring->tx_stats)); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + tx_ring->acum_pkts = 0; + + /* Make sure that drbr is empty */ + ENA_RING_MTX_LOCK(tx_ring); + drbr_flush(adapter->ifp, tx_ring->br); + ENA_RING_MTX_UNLOCK(tx_ring); + + /* ... and create the buffer DMA maps */ + for (i = 0; i < tx_ring->ring_size; i++) { + err = bus_dmamap_create(adapter->tx_buf_tag, 0, + &tx_ring->tx_buffer_info[i].dmamap); + if (unlikely(err != 0)) { - ena_trace(NULL, ENA_ALERT, ++ ena_log(pdev, ERR, + "Unable to create Tx DMA map for buffer %d\n", + i); + goto err_map_release; + } + +#ifdef DEV_NETMAP + if (adapter->ifp->if_capenable & IFCAP_NETMAP) { + map = tx_ring->tx_buffer_info[i].nm_info.map_seg; + for (j = 0; j < ENA_PKT_MAX_BUFS; j++) { + err = bus_dmamap_create(adapter->tx_buf_tag, 0, + &map[j]); + if (unlikely(err != 0)) { - ena_trace(NULL, ENA_ALERT, "Unable to create " ++ ena_log(pdev, ERR, ++ "Unable to create " + "Tx DMA for buffer %d %d\n", i, j); + goto err_map_release; + } + } + } +#endif /* DEV_NETMAP */ + } + + /* Allocate taskqueues */ + TASK_INIT(&tx_ring->enqueue_task, 0, ena_deferred_mq_start, tx_ring); + tx_ring->enqueue_tq = taskqueue_create_fast("ena_tx_enque", M_NOWAIT, + taskqueue_thread_enqueue, &tx_ring->enqueue_tq); + if (unlikely(tx_ring->enqueue_tq == NULL)) { - ena_trace(NULL, ENA_ALERT, ++ ena_log(pdev, ERR, + "Unable to create taskqueue for enqueue task\n"); + i = tx_ring->ring_size; + goto err_map_release; + } + + tx_ring->running = true; + + taskqueue_start_threads(&tx_ring->enqueue_tq, 1, PI_NET, + "%s txeq %d", device_get_nameunit(adapter->pdev), que->cpu); + + return (0); + +err_map_release: + ena_release_all_tx_dmamap(tx_ring); +err_tx_ids_free: + free(tx_ring->free_tx_ids, M_DEVBUF); + tx_ring->free_tx_ids = NULL; +err_buf_info_free: + free(tx_ring->tx_buffer_info, M_DEVBUF); + tx_ring->tx_buffer_info = NULL; + + return (ENOMEM); +} + +/** + * ena_free_tx_resources - Free Tx Resources per Queue + * @adapter: network interface device structure + * @qid: queue index + * + * Free all transmit software resources + **/ +static void +ena_free_tx_resources(struct ena_adapter *adapter, int qid) +{ + struct ena_ring *tx_ring = &adapter->tx_ring[qid]; +#ifdef DEV_NETMAP + struct ena_netmap_tx_info *nm_info; + int j; +#endif /* DEV_NETMAP */ + + while (taskqueue_cancel(tx_ring->enqueue_tq, &tx_ring->enqueue_task, + NULL)) + taskqueue_drain(tx_ring->enqueue_tq, &tx_ring->enqueue_task); + + taskqueue_free(tx_ring->enqueue_tq); + + ENA_RING_MTX_LOCK(tx_ring); + /* Flush buffer ring, */ + drbr_flush(adapter->ifp, tx_ring->br); + + /* Free buffer DMA maps, */ + for (int i = 0; i < tx_ring->ring_size; i++) { + bus_dmamap_sync(adapter->tx_buf_tag, + tx_ring->tx_buffer_info[i].dmamap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(adapter->tx_buf_tag, + tx_ring->tx_buffer_info[i].dmamap); + bus_dmamap_destroy(adapter->tx_buf_tag, + tx_ring->tx_buffer_info[i].dmamap); + +#ifdef DEV_NETMAP + if (adapter->ifp->if_capenable & IFCAP_NETMAP) { + nm_info = &tx_ring->tx_buffer_info[i].nm_info; + for (j = 0; j < ENA_PKT_MAX_BUFS; j++) { + if (nm_info->socket_buf_idx[j] != 0) { + bus_dmamap_sync(adapter->tx_buf_tag, + nm_info->map_seg[j], + BUS_DMASYNC_POSTWRITE); + ena_netmap_unload(adapter, + nm_info->map_seg[j]); + } + bus_dmamap_destroy(adapter->tx_buf_tag, + nm_info->map_seg[j]); + nm_info->socket_buf_idx[j] = 0; + } + } +#endif /* DEV_NETMAP */ + + m_freem(tx_ring->tx_buffer_info[i].mbuf); + tx_ring->tx_buffer_info[i].mbuf = NULL; + } + ENA_RING_MTX_UNLOCK(tx_ring); + + /* And free allocated memory. */ + free(tx_ring->tx_buffer_info, M_DEVBUF); + tx_ring->tx_buffer_info = NULL; + + free(tx_ring->free_tx_ids, M_DEVBUF); + tx_ring->free_tx_ids = NULL; + + free(tx_ring->push_buf_intermediate_buf, M_DEVBUF); + tx_ring->push_buf_intermediate_buf = NULL; +} + +/** + * ena_setup_all_tx_resources - allocate all queues Tx resources + * @adapter: network interface device structure + * + * Returns 0 on success, otherwise on failure. + **/ +static int +ena_setup_all_tx_resources(struct ena_adapter *adapter) +{ + int i, rc; + + for (i = 0; i < adapter->num_io_queues; i++) { + rc = ena_setup_tx_resources(adapter, i); + if (rc != 0) { - device_printf(adapter->pdev, ++ ena_log(adapter->pdev, ERR, + "Allocation for Tx Queue %u failed\n", i); + goto err_setup_tx; + } + } + + return (0); + +err_setup_tx: + /* Rewind the index freeing the rings as we go */ + while (i--) + ena_free_tx_resources(adapter, i); + return (rc); +} + +/** + * ena_free_all_tx_resources - Free Tx Resources for All Queues + * @adapter: network interface device structure + * + * Free all transmit software resources + **/ +static void +ena_free_all_tx_resources(struct ena_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_io_queues; i++) + ena_free_tx_resources(adapter, i); +} + +/** + * ena_setup_rx_resources - allocate Rx resources (Descriptors) + * @adapter: network interface device structure + * @qid: queue index + * + * Returns 0 on success, otherwise on failure. + **/ +static int +ena_setup_rx_resources(struct ena_adapter *adapter, unsigned int qid) +{ ++ device_t pdev = adapter->pdev; + struct ena_que *que = &adapter->que[qid]; + struct ena_ring *rx_ring = que->rx_ring; + int size, err, i; + + size = sizeof(struct ena_rx_buffer) * rx_ring->ring_size; + +#ifdef DEV_NETMAP + ena_netmap_reset_rx_ring(adapter, qid); + rx_ring->initialized = false; +#endif /* DEV_NETMAP */ + + /* + * Alloc extra element so in rx path + * we can always prefetch rx_info + 1 + */ + size += sizeof(struct ena_rx_buffer); + + rx_ring->rx_buffer_info = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); + + size = sizeof(uint16_t) * rx_ring->ring_size; + rx_ring->free_rx_ids = malloc(size, M_DEVBUF, M_WAITOK); + + for (i = 0; i < rx_ring->ring_size; i++) + rx_ring->free_rx_ids[i] = i; + + /* Reset RX statistics. */ + ena_reset_counters((counter_u64_t *)&rx_ring->rx_stats, + sizeof(rx_ring->rx_stats)); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + + /* ... and create the buffer DMA maps */ + for (i = 0; i < rx_ring->ring_size; i++) { + err = bus_dmamap_create(adapter->rx_buf_tag, 0, + &(rx_ring->rx_buffer_info[i].map)); + if (err != 0) { - ena_trace(NULL, ENA_ALERT, ++ ena_log(pdev, ERR, + "Unable to create Rx DMA map for buffer %d\n", i); + goto err_buf_info_unmap; + } + } + + /* Create LRO for the ring */ + if ((adapter->ifp->if_capenable & IFCAP_LRO) != 0) { + int err = tcp_lro_init(&rx_ring->lro); + if (err != 0) { - device_printf(adapter->pdev, - "LRO[%d] Initialization failed!\n", qid); ++ ena_log(pdev, ERR, "LRO[%d] Initialization failed!\n", ++ qid); + } else { - ena_trace(NULL, ENA_INFO, - "RX Soft LRO[%d] Initialized\n", qid); ++ ena_log(pdev, DBG, "RX Soft LRO[%d] Initialized\n", ++ qid); + rx_ring->lro.ifp = adapter->ifp; + } + } + + return (0); + +err_buf_info_unmap: + while (i--) { + bus_dmamap_destroy(adapter->rx_buf_tag, + rx_ring->rx_buffer_info[i].map); + } + + free(rx_ring->free_rx_ids, M_DEVBUF); + rx_ring->free_rx_ids = NULL; + free(rx_ring->rx_buffer_info, M_DEVBUF); + rx_ring->rx_buffer_info = NULL; *** 6157 LINES SKIPPED ***