Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Import source for FreeBSD Amazon El...



details:   https://anonhg.NetBSD.org/src/rev/0c5869efd613
branches:  trunk
changeset: 319157:0c5869efd613
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sat May 19 09:18:31 2018 +0000

description:
Import source for FreeBSD Amazon Elastic Network Adapter (ENA) NIC driver
for reference. Needs a lot of work to port over.

Remapped filenames from FreeBSD to NetBSD structure:
sys/dev/ena/ena.c -> sys/dev/pci/if_ena.c
sys/dev/ena/ena.h -> sys/dev/pci/if_enavar.h

ena_sysctl.* not imported, if needed later will be merged into if_ena.c

diffstat:

 sys/dev/pci/if_ena.c    |  3953 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/if_enavar.h |   404 ++++
 2 files changed, 4357 insertions(+), 0 deletions(-)

diffs (truncated from 4365 to 300 lines):

diff -r e481bed63eca -r 0c5869efd613 sys/dev/pci/if_ena.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/if_ena.c      Sat May 19 09:18:31 2018 +0000
@@ -0,0 +1,3953 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2015-2017 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/ena/ena.c 333456 2018-05-10 09:37:54Z mw $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/smp.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+#include <sys/time.h>
+#include <sys/eventhandler.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/in_cksum.h>
+
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/rss_config.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <netinet/in_rss.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include "ena.h"
+#include "ena_sysctl.h"
+
+/*********************************************************
+ *  Function prototypes
+ *********************************************************/
+static int     ena_probe(device_t);
+static void    ena_intr_msix_mgmnt(void *);
+static int     ena_allocate_pci_resources(struct ena_adapter*);
+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(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 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 inline int validate_rx_req_id(struct ena_ring *, uint16_t);
+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 int     ena_refill_rx_bufs(struct ena_ring *, uint32_t);
+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_tx_cleanup(struct ena_ring *);
+static void    ena_deferred_rx_cleanup(void *, int);
+static int     ena_rx_cleanup(struct ena_ring *);
+static inline int validate_tx_req_id(struct ena_ring *, uint16_t);
+static void    ena_rx_hash_mbuf(struct ena_ring *, struct ena_com_rx_ctx *,
+    struct mbuf *);
+static struct mbuf* ena_rx_mbuf(struct ena_ring *, struct ena_com_rx_buf_info *,
+    struct ena_com_rx_ctx *, uint16_t *);
+static inline void ena_rx_checksum(struct ena_ring *, struct ena_com_rx_ctx *,
+    struct mbuf *);
+static void    ena_handle_msix(void *);
+static int     ena_enable_msix(struct ena_adapter *);
+static void    ena_setup_mgmnt_intr(struct ena_adapter *);
+static void    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 int     ena_up(struct ena_adapter *);
+static void    ena_down(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 void    ena_tx_csum(struct ena_com_tx_ctx *, struct mbuf *);
+static int     ena_check_and_collapse_mbuf(struct ena_ring *tx_ring,
+    struct mbuf **mbuf);
+static int     ena_xmit_mbuf(struct ena_ring *, struct mbuf **);
+static void    ena_start_xmit(struct ena_ring *);
+static int     ena_mq_start(if_t, struct mbuf *);
+static void    ena_deferred_mq_start(void *, int);
+static void    ena_qflush(if_t);
+static int     ena_calc_io_queue_num(struct ena_adapter *,
+    struct ena_com_dev_get_features_ctx *);
+static int     ena_calc_queue_size(struct ena_adapter *, uint16_t *,
+    uint16_t *, struct ena_com_dev_get_features_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 *);
+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 *,
+    int);
+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 void    ena_timer_service(void *);
+
+static char ena_version[] = DEVICE_NAME DRV_MODULE_NAME " v" DRV_MODULE_VERSION;
+
+static SYSCTL_NODE(_hw, OID_AUTO, ena, CTLFLAG_RD, 0, "ENA driver parameters");
+
+/*
+ * Tuneable number of buffers in the buf-ring (drbr)
+ */
+static int ena_buf_ring_size = 4096;
+SYSCTL_INT(_hw_ena, OID_AUTO, buf_ring_size, CTLFLAG_RWTUN,
+    &ena_buf_ring_size, 0, "Size of the bufring");
+
+/*
+ * Logging level for changing verbosity of the output
+ */
+int ena_log_level = ENA_ALERT | ENA_WARNING;
+SYSCTL_INT(_hw_ena, OID_AUTO, log_level, CTLFLAG_RWTUN,
+    &ena_log_level, 0, "Logging level indicating verbosity of the logs");
+
+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_LLQ_PF, 0},
+    { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_VF, 0},
+    { PCI_VENDOR_ID_AMAZON, PCI_DEV_ID_ENA_LLQ_VF, 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)
+{
+       struct ena_adapter* adapter = device_get_softc(dmadev);
+       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 */
+           8, 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(ENA_ALERT, "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(ENA_ALERT, "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(ENA_ALERT, ": bus_dmamap_load failed: %d\n", error);
+               goto fail_map_load;
+       }
+
+       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;
+
+       return (error);
+}
+
+static int
+ena_allocate_pci_resources(struct ena_adapter* adapter)
+{
+       device_t pdev = adapter->pdev;
+       int rid;
+
+       rid = PCIR_BAR(ENA_REG_BAR);
+       adapter->memory = NULL;
+       adapter->registers = bus_alloc_resource_any(pdev, SYS_RES_MEMORY,
+           &rid, RF_ACTIVE);
+       if (unlikely(adapter->registers == NULL)) {
+               device_printf(pdev, "Unable to allocate bus resource: "



Home | Main Index | Thread Index | Old Index