Module Name: src Committed By: jdolecek Date: Sat Jun 16 15:00:35 UTC 2018
Modified Files: src/sys/dev/pci: if_ena.c if_enavar.h src/sys/external/bsd/ena-com: ena_plat.h Log Message: make ena(4) compile, with best efford exercised to convert code to NetBSD equivalents; where possible left the original code intact to make it easier to compare against FreeBSD original made non-working stubs for some functions which don't have direct equivalent yet - this includes all of <sys/buf_ring.h>, m_getjcl(), m_append, and m_collapse(); these need to be adressed left XXX/TODO in if_enavar.h, colocated with the non-working stubs To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/if_ena.c cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pci/if_enavar.h cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/ena-com/ena_plat.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_ena.c diff -u src/sys/dev/pci/if_ena.c:1.3 src/sys/dev/pci/if_ena.c:1.4 --- src/sys/dev/pci/if_ena.c:1.3 Fri Jun 1 09:34:39 2018 +++ src/sys/dev/pci/if_ena.c Sat Jun 16 15:00:35 2018 @@ -31,7 +31,7 @@ #if 0 __FBSDID("$FreeBSD: head/sys/dev/ena/ena.c 333456 2018-05-10 09:37:54Z mw $"); #endif -__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.3 2018/06/01 09:34:39 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.4 2018/06/16 15:00:35 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -47,31 +47,37 @@ __KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1 #include <sys/sysctl.h> #include <sys/time.h> #include <sys/workqueue.h> +#include <sys/callout.h> +#include <sys/interrupt.h> +#include <sys/cpu.h> #include <sys/bus.h> +#include <net/if_ether.h> +#include <net/if_vlanvar.h> + #include <dev/pci/if_enavar.h> /********************************************************* * Function prototypes *********************************************************/ static int ena_probe(device_t, cfdata_t, void *); -static void ena_intr_msix_mgmnt(void *); -static int ena_allocate_pci_resources(struct ena_adapter*); +static int ena_intr_msix_mgmnt(void *); +static int ena_allocate_pci_resources(struct pci_attach_args *, + struct ena_adapter *); static void ena_free_pci_resources(struct ena_adapter *); static int ena_change_mtu(struct ifnet *, int); -static inline void ena_alloc_counters(struct evcnt *, int); -static inline void ena_free_counters(struct evcnt *, int); -static inline void ena_reset_counters(struct evcnt *, 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 *); +#if 0 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 *); +#endif 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 *); @@ -96,19 +102,19 @@ static void ena_destroy_all_rx_queues(st 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 void ena_deferred_rx_cleanup(struct work *, void *); static int ena_rx_cleanup(struct ena_ring *); static inline int validate_tx_req_id(struct ena_ring *, uint16_t); +#if 0 static void ena_rx_hash_mbuf(struct ena_ring *, struct ena_com_rx_ctx *, struct mbuf *); +#endif 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_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 *); @@ -125,7 +131,7 @@ static uint64_t ena_get_counter(struct i #endif static int ena_media_change(struct ifnet *); static void ena_media_status(struct ifnet *, struct ifmediareq *); -static void ena_init(void *); +static int ena_init(struct ifnet *); static int ena_ioctl(struct ifnet *, u_long, void *); static int ena_get_dev_offloads(struct ena_com_dev_get_features_ctx *); static void ena_update_host_info(struct ena_admin_host_info *, struct ifnet *); @@ -138,17 +144,21 @@ static int ena_check_and_collapse_mbuf(s static int ena_xmit_mbuf(struct ena_ring *, struct mbuf **); static void ena_start_xmit(struct ena_ring *); static int ena_mq_start(struct ifnet *, struct mbuf *); -static void ena_deferred_mq_start(void *, int); +static void ena_deferred_mq_start(struct work *, void *); +#if 0 static void ena_qflush(struct ifnet *); -static int ena_calc_io_queue_num(struct ena_adapter *, - struct ena_com_dev_get_features_ctx *); +#endif +static int ena_calc_io_queue_num(struct pci_attach_args *, + 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 *); +#if 0 static int ena_rss_init_default(struct ena_adapter *); static void ena_rss_init_default_deferred(void *); +#endif static void ena_config_host_info(struct ena_com_dev *); -static int ena_attach(device_t parent, device_t self, void *aux); -static int ena_detach(device_t); +static void ena_attach(device_t, device_t, void *); +static int ena_detach(device_t, int); 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 *, @@ -217,8 +227,8 @@ ena_dma_alloc(device_t dmadev, bus_size_ dma->tag = adapter->sc_dmat; - if (bus_dmamap_create(dma->tag, maxsize, 1, maxsize, 0, - BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &dma->map) != 0) { + if ((error = bus_dmamap_create(dma->tag, maxsize, 1, maxsize, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &dma->map)) != 0) { ena_trace(ENA_ALERT, "bus_dmamap_create(%ju) failed: %d\n", (uintmax_t)maxsize, error); goto fail_create; @@ -262,19 +272,19 @@ fail_create: } static int -ena_allocate_pci_resources(struct ena_adapter* adapter) +ena_allocate_pci_resources(struct pci_attach_args *pa, + struct ena_adapter *adapter) { - device_t pdev = adapter->pdev; - int rid; + bus_size_t size; - 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: " - "registers\n"); - return (ENXIO); + /* + * Map control/status registers. + */ + pcireg_t memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, ENA_REG_BAR); + if (pci_mapreg_map(pa, ENA_REG_BAR, memtype, 0, &adapter->sc_btag, + &adapter->sc_bhandle, NULL, &size)) { + aprint_error(": can't map mem space\n"); + return ENXIO; } return (0); @@ -283,17 +293,7 @@ ena_allocate_pci_resources(struct ena_ad 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); - } + /* Nothing to do */ } static int @@ -339,16 +339,84 @@ ena_change_mtu(struct ifnet *ifp, int ne return (rc); } +#define EVCNT_INIT(st, f) \ + do { \ + evcnt_attach_dynamic(&st->f, EVCNT_TYPE_MISC, NULL, \ + st->name, #f); \ + } while (0) + static inline void -ena_alloc_counters(struct evcnt *begin, int size) +ena_alloc_counters_rx(struct ena_stats_rx *st, int queue) { - struct evcnt *end = (struct evcnt *)((char *)begin + size); + snprintf(st->name, sizeof(st->name), "ena rxq%d", queue); - for (; begin < end; ++begin) - *begin = counter_u64_alloc(M_WAITOK); + EVCNT_INIT(st, cnt); + EVCNT_INIT(st, bytes); + EVCNT_INIT(st, refil_partial); + EVCNT_INIT(st, bad_csum); + EVCNT_INIT(st, mjum_alloc_fail); + EVCNT_INIT(st, mbuf_alloc_fail); + EVCNT_INIT(st, dma_mapping_err); + EVCNT_INIT(st, bad_desc_num); + EVCNT_INIT(st, bad_req_id); + EVCNT_INIT(st, empty_rx_ring); + + /* Make sure all code is updated when new fields added */ + CTASSERT(offsetof(struct ena_stats_rx, empty_rx_ring) + + sizeof(st->empty_rx_ring) == sizeof(*st)); +} + +static inline void +ena_alloc_counters_tx(struct ena_stats_tx *st, int queue) +{ + snprintf(st->name, sizeof(st->name), "ena txq%d", queue); + + EVCNT_INIT(st, cnt); + EVCNT_INIT(st, bytes); + EVCNT_INIT(st, prepare_ctx_err); + EVCNT_INIT(st, dma_mapping_err); + EVCNT_INIT(st, doorbells); + EVCNT_INIT(st, missing_tx_comp); + EVCNT_INIT(st, bad_req_id); + EVCNT_INIT(st, collapse); + EVCNT_INIT(st, collapse_err); + + /* Make sure all code is updated when new fields added */ + CTASSERT(offsetof(struct ena_stats_tx, collapse_err) + + sizeof(st->collapse_err) == sizeof(*st)); } static inline void +ena_alloc_counters_dev(struct ena_stats_dev *st, int queue) +{ + snprintf(st->name, sizeof(st->name), "ena dev ioq%d", queue); + + EVCNT_INIT(st, wd_expired); + EVCNT_INIT(st, interface_up); + EVCNT_INIT(st, interface_down); + EVCNT_INIT(st, admin_q_pause); + + /* Make sure all code is updated when new fields added */ + CTASSERT(offsetof(struct ena_stats_dev, admin_q_pause) + + sizeof(st->admin_q_pause) == sizeof(*st)); +} + +static inline void +ena_alloc_counters_hwstats(struct ena_hw_stats *st, int queue) +{ + snprintf(st->name, sizeof(st->name), "ena hw ioq%d", queue); + + EVCNT_INIT(st, rx_packets); + EVCNT_INIT(st, tx_packets); + EVCNT_INIT(st, rx_bytes); + EVCNT_INIT(st, tx_bytes); + EVCNT_INIT(st, rx_drops); + + /* Make sure all code is updated when new fields added */ + CTASSERT(offsetof(struct ena_hw_stats, rx_drops) + + sizeof(st->rx_drops) == sizeof(*st)); +} +static inline void ena_free_counters(struct evcnt *begin, int size) { struct evcnt *end = (struct evcnt *)((char *)begin + size); @@ -406,8 +474,7 @@ ena_init_io_rings(struct ena_adapter *ad M_WAITOK, &txr->ring_mtx); /* Alloc TX statistics. */ - ena_alloc_counters((struct evcnt *)&txr->tx_stats, - sizeof(txr->tx_stats)); + ena_alloc_counters_tx(&txr->tx_stats, i); /* RX specific ring state */ rxr->ring_size = adapter->rx_ring_size; @@ -415,8 +482,7 @@ ena_init_io_rings(struct ena_adapter *ad ena_com_get_nonadaptive_moderation_interval_rx(ena_dev); /* Alloc RX statistics. */ - ena_alloc_counters((struct evcnt *)&rxr->rx_stats, - sizeof(rxr->rx_stats)); + ena_alloc_counters_rx(&rxr->rx_stats, i); /* Initialize locks */ snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)", @@ -563,7 +629,9 @@ ena_setup_tx_resources(struct ena_adapte /* ... and create the buffer DMA maps */ for (i = 0; i < tx_ring->ring_size; i++) { - err = bus_dmamap_create(adapter->sc_dmat, 0, + err = bus_dmamap_create(adapter->sc_dmat, + ENA_TSO_MAXSIZE, adapter->max_tx_sgl_size - 1, + ENA_TSO_MAXSIZE, 0, 0, &tx_ring->tx_buffer_info[i].map); if (unlikely(err != 0)) { ena_trace(ENA_ALERT, @@ -572,17 +640,17 @@ ena_setup_tx_resources(struct ena_adapte } } - /* 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)) { + /* Allocate workqueues */ + int rc = workqueue_create(&tx_ring->enqueue_tq, "ena_tx_enque", + ena_deferred_mq_start, tx_ring, 0, IPL_NET, 0); + if (unlikely(rc == 0)) { ena_trace(ENA_ALERT, - "Unable to create taskqueue for enqueue task\n"); + "Unable to create workqueue for enqueue task\n"); i = tx_ring->ring_size; goto err_buf_info_unmap; } +#if 0 /* RSS set cpu for thread */ #ifdef RSS CPU_SETOF(que->cpu, &cpu_mask); @@ -593,6 +661,7 @@ ena_setup_tx_resources(struct ena_adapte taskqueue_start_threads(&tx_ring->enqueue_tq, 1, IPL_NET, "%s txeq %d", device_xname(adapter->pdev), que->cpu); #endif /* RSS */ +#endif return (0); @@ -622,11 +691,9 @@ ena_free_tx_resources(struct ena_adapter { struct ena_ring *tx_ring = &adapter->tx_ring[qid]; - 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); + workqueue_wait(tx_ring->enqueue_tq, &tx_ring->enqueue_task); + workqueue_destroy(tx_ring->enqueue_tq); + tx_ring->enqueue_tq = NULL; ENA_RING_MTX_LOCK(tx_ring); /* Flush buffer ring, */ @@ -754,7 +821,9 @@ ena_setup_rx_resources(struct ena_adapte /* ... and create the buffer DMA maps */ for (i = 0; i < rx_ring->ring_size; i++) { - err = bus_dmamap_create(adapter->sc_dmat, 0, + err = bus_dmamap_create(adapter->sc_dmat, + MJUM16BYTES, adapter->max_rx_sgl_size, MJUM16BYTES, + 0, 0, &(rx_ring->rx_buffer_info[i].map)); if (err != 0) { ena_trace(ENA_ALERT, @@ -778,11 +847,16 @@ ena_setup_rx_resources(struct ena_adapte } #endif - /* Allocate taskqueues */ - TASK_INIT(&rx_ring->cmpl_task, 0, ena_deferred_rx_cleanup, rx_ring); - rx_ring->cmpl_tq = taskqueue_create_fast("ena RX completion", M_WAITOK, - taskqueue_thread_enqueue, &rx_ring->cmpl_tq); + /* Allocate workqueues */ + int rc = workqueue_create(&rx_ring->cmpl_tq, "ena RX completion", + ena_deferred_rx_cleanup, rx_ring, 0, IPL_NET, 0); + if (unlikely(rc != 0)) { + ena_trace(ENA_ALERT, + "Unable to create workqueue for RX completion task\n"); + goto err_buf_info_unmap; + } +#if 0 /* RSS set cpu for thread */ #ifdef RSS CPU_SETOF(que->cpu, &cpu_mask); @@ -793,6 +867,7 @@ ena_setup_rx_resources(struct ena_adapte taskqueue_start_threads(&rx_ring->cmpl_tq, 1, IPL_NET, "%s rx_ring cmpl %d", device_xname(adapter->pdev), que->cpu); #endif +#endif return (0); @@ -821,10 +896,9 @@ ena_free_rx_resources(struct ena_adapter { struct ena_ring *rx_ring = &adapter->rx_ring[qid]; - while (taskqueue_cancel(rx_ring->cmpl_tq, &rx_ring->cmpl_task, NULL) != 0) - taskqueue_drain(rx_ring->cmpl_tq, &rx_ring->cmpl_task); - - taskqueue_free(rx_ring->cmpl_tq); + workqueue_wait(rx_ring->cmpl_tq, &rx_ring->cmpl_task); + workqueue_destroy(rx_ring->cmpl_tq); + rx_ring->cmpl_tq = NULL; /* Free buffer DMA maps, */ for (int i = 0; i < rx_ring->ring_size; i++) { @@ -897,8 +971,7 @@ ena_alloc_rx_mbuf(struct ena_adapter *ad struct ena_ring *rx_ring, struct ena_rx_buffer *rx_info) { struct ena_com_buf *ena_buf; - bus_dma_segment_t segs[1]; - int nsegs, error; + int error; int mlen; /* if previous allocated frag is not used */ @@ -926,21 +999,21 @@ ena_alloc_rx_mbuf(struct ena_adapter *ad ena_trace(ENA_DBG | ENA_RSC | ENA_RXPTH, "Using tag %p for buffers' DMA mapping, mbuf %p len: %d", adapter->sc_dmat,rx_info->mbuf, rx_info->mbuf->m_len); - error = bus_dmamap_load_mbuf_sg(adapter->sc_dmat, rx_info->map, - rx_info->mbuf, segs, &nsegs, BUS_DMA_NOWAIT); - if (unlikely((error != 0) || (nsegs != 1))) { + error = bus_dmamap_load_mbuf(adapter->sc_dmat, rx_info->map, + rx_info->mbuf, BUS_DMA_NOWAIT); + if (unlikely((error != 0) || (rx_info->map->dm_nsegs != 1))) { ena_trace(ENA_WARNING, "failed to map mbuf, error: %d, " - "nsegs: %d\n", error, nsegs); + "nsegs: %d\n", error, rx_info->map->dm_nsegs); counter_u64_add(rx_ring->rx_stats.dma_mapping_err, 1); goto exit; } - bus_dmamap_sync(adapter->sc_dmat, rx_info->map, 0, mlen, - BUS_DMASYNC_PREREAD); + bus_dmamap_sync(adapter->sc_dmat, rx_info->map, 0, + rx_info->map->dm_mapsize, BUS_DMASYNC_PREREAD); ena_buf = &rx_info->ena_buf; - ena_buf->paddr = segs[0].ds_addr; + ena_buf->paddr = rx_info->map->dm_segs[0].ds_addr; ena_buf->len = mlen; ena_trace(ENA_DBG | ENA_RSC | ENA_RXPTH, @@ -1349,11 +1422,12 @@ ena_tx_cleanup(struct ena_ring *tx_ring) ena_com_update_dev_comp_head(io_cq); } - taskqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task); + workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task, NULL); return (work_done); } +#if 0 static void ena_rx_hash_mbuf(struct ena_ring *rx_ring, struct ena_com_rx_ctx *ena_rx_ctx, struct mbuf *mbuf) @@ -1405,6 +1479,7 @@ ena_rx_hash_mbuf(struct ena_ring *rx_rin M_HASHTYPE_SET(mbuf, M_HASHTYPE_NONE); } } +#endif /** * ena_rx_mbuf - assemble mbuf from descriptors @@ -1444,10 +1519,12 @@ ena_rx_mbuf(struct ena_ring *rx_ring, st KASSERT(mbuf->m_flags & M_PKTHDR); mbuf->m_pkthdr.len = len; mbuf->m_len = len; - mbuf->m_pkthdr.rcvif = rx_ring->que->adapter->ifp; + m_set_rcvif(mbuf, rx_ring->que->adapter->ifp); /* Fill mbuf with hash key and it's interpretation for optimization */ +#if 0 ena_rx_hash_mbuf(rx_ring, ena_rx_ctx, mbuf); +#endif ena_trace(ENA_DBG | ENA_RXPTH, "rx mbuf 0x%p, flags=0x%x, len: %d", mbuf, mbuf->m_flags, mbuf->m_pkthdr.len); @@ -1531,18 +1608,17 @@ ena_rx_checksum(struct ena_ring *rx_ring (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP)) { if (ena_rx_ctx->l4_csum_err) { /* TCP/UDP checksum error */ - mbuf->m_pkthdr.csum_flags = 0; + mbuf->m_pkthdr.csum_flags = M_CSUM_IPv4_BAD; counter_u64_add(rx_ring->rx_stats.bad_csum, 1); ena_trace(ENA_DBG, "RX L4 checksum error"); } else { - mbuf->m_pkthdr.csum_flags = CSUM_IP_CHECKED; - mbuf->m_pkthdr.csum_flags |= CSUM_IP_VALID; + mbuf->m_pkthdr.csum_flags = M_CSUM_IPv4; } } } static void -ena_deferred_rx_cleanup(void *arg, int pending) +ena_deferred_rx_cleanup(struct work *wk, void *arg) { struct ena_ring *rx_ring = arg; int budget = CLEAN_BUDGET; @@ -1576,7 +1652,9 @@ ena_rx_cleanup(struct ena_ring *rx_ring) uint16_t next_to_clean; uint32_t refill_required; uint32_t refill_threshold; +#ifdef LRO uint32_t do_if_input = 0; +#endif unsigned int qid; int rc, i; int budget = RX_BUDGET; @@ -1625,8 +1703,11 @@ ena_rx_cleanup(struct ena_ring *rx_ring) break; } - if (((ifp->if_capenable & IFCAP_RXCSUM) != 0) || - ((ifp->if_capenable & IFCAP_RXCSUM_IPV6) != 0)) { + if (((ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) != 0) || + ((ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) != 0) || + ((ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) != 0) || + ((ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) != 0) || + ((ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) != 0)) { ena_rx_checksum(rx_ring, &ena_rx_ctx, mbuf); } @@ -1699,7 +1780,7 @@ error: * ena_handle_msix - MSIX Interrupt Handler for admin/async queue * @arg: interrupt number **/ -static void +static int ena_intr_msix_mgmnt(void *arg) { struct ena_adapter *adapter = (struct ena_adapter *)arg; @@ -1707,13 +1788,15 @@ ena_intr_msix_mgmnt(void *arg) ena_com_admin_q_comp_intr_handler(adapter->ena_dev); if (likely(adapter->running)) ena_com_aenq_intr_handler(adapter->ena_dev, arg); + + return 1; } /** * ena_handle_msix - MSIX Interrupt Handler for Tx/Rx * @arg: interrupt number **/ -static void +static int ena_handle_msix(void *arg) { struct ena_que *que = arg; @@ -1726,8 +1809,8 @@ ena_handle_msix(void *arg) int qid, ena_qid; int txc, rxc, i; - if (unlikely((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)) - return; + if (unlikely((if_getdrvflags(ifp) & IFF_RUNNING) == 0)) + return 0; ena_trace(ENA_DBG, "MSI-X TX/RX routine"); @@ -1755,8 +1838,8 @@ ena_handle_msix(void *arg) txc = ena_tx_cleanup(tx_ring); ENA_RING_MTX_UNLOCK(tx_ring); - if (unlikely((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)) - return; + if (unlikely((if_getdrvflags(ifp) & IFF_RUNNING) == 0)) + return 0; if ((txc != TX_BUDGET) && (rxc != RX_BUDGET)) break; @@ -1768,74 +1851,45 @@ ena_handle_msix(void *arg) TX_IRQ_INTERVAL, true); ena_com_unmask_intr(io_cq, &intr_reg); + + return 1; } static int ena_enable_msix(struct ena_adapter *adapter) { - device_t dev = adapter->pdev; - int msix_vecs, msix_req; - int i, rc = 0; + int msix_req; + int counts[PCI_INTR_TYPE_SIZE]; + int max_type; /* Reserved the max msix vectors we might need */ - msix_vecs = ENA_MAX_MSIX_VEC(adapter->num_queues); - - adapter->msix_entries = malloc(msix_vecs * sizeof(struct msix_entry), - M_DEVBUF, M_WAITOK | M_ZERO); + msix_req = ENA_MAX_MSIX_VEC(adapter->num_queues); - ena_trace(ENA_DBG, "trying to enable MSI-X, vectors: %d", msix_vecs); + counts[PCI_INTR_TYPE_INTX] = 0; + counts[PCI_INTR_TYPE_MSI] = 0; + counts[PCI_INTR_TYPE_MSIX] = msix_req; + max_type = PCI_INTR_TYPE_MSIX; + + if (pci_intr_alloc(&adapter->sc_pa, &adapter->sc_intrs, counts, + max_type) != 0) { + aprint_error_dev(adapter->pdev, + "failed to allocate interrupt\n"); + return ENOSPC; + } - for (i = 0; i < msix_vecs; i++) { - adapter->msix_entries[i].entry = i; - /* Vectors must start from 1 */ - adapter->msix_entries[i].vector = i + 1; - } - - msix_req = msix_vecs; - rc = pci_alloc_msix(dev, &msix_vecs); - if (unlikely(rc != 0)) { - device_printf(dev, - "Failed to enable MSIX, vectors %d rc %d\n", msix_vecs, rc); + adapter->sc_nintrs = counts[PCI_INTR_TYPE_MSIX]; - rc = ENOSPC; - goto err_msix_free; - } - - if (msix_vecs != msix_req) { - device_printf(dev, "Enable only %d MSI-x (out of %d), reduce " - "the number of queues\n", msix_vecs, msix_req); - adapter->num_queues = msix_vecs - ENA_ADMIN_MSIX_VEC; + if (counts[PCI_INTR_TYPE_MSIX] != msix_req) { + device_printf(adapter->pdev, + "Enable only %d MSI-x (out of %d), reduce " + "the number of queues\n", adapter->sc_nintrs, msix_req); + adapter->num_queues = adapter->sc_nintrs - ENA_ADMIN_MSIX_VEC; } - adapter->msix_vecs = msix_vecs; - adapter->msix_enabled = true; - - return (0); - -err_msix_free: - free(adapter->msix_entries, M_DEVBUF); - adapter->msix_entries = NULL; - - return (rc); -} - -static void -ena_setup_mgmnt_intr(struct ena_adapter *adapter) -{ - - snprintf(adapter->irq_tbl[ENA_MGMNT_IRQ_IDX].name, - ENA_IRQNAME_SIZE, "ena-mgmnt@pci:%s", - device_xname(adapter->pdev)); - /* - * Handler is NULL on purpose, it will be set - * when mgmnt interrupt is acquired - */ - adapter->irq_tbl[ENA_MGMNT_IRQ_IDX].handler = NULL; - adapter->irq_tbl[ENA_MGMNT_IRQ_IDX].data = adapter; - adapter->irq_tbl[ENA_MGMNT_IRQ_IDX].vector = - adapter->msix_entries[ENA_MGMNT_IRQ_IDX].vector; + return 0; } +#if 0 static void ena_setup_io_intr(struct ena_adapter *adapter) { @@ -1869,204 +1923,145 @@ ena_setup_io_intr(struct ena_adapter *ad #endif } } +#endif static int ena_request_mgmnt_irq(struct ena_adapter *adapter) { - struct ena_irq *irq; - unsigned long flags; - int rc, rcc; - - flags = RF_ACTIVE | RF_SHAREABLE; - - irq = &adapter->irq_tbl[ENA_MGMNT_IRQ_IDX]; - irq->res = bus_alloc_resource_any(adapter->pdev, SYS_RES_IRQ, - &irq->vector, flags); - - if (unlikely(irq->res == NULL)) { - device_printf(adapter->pdev, "could not allocate " - "irq vector: %d\n", irq->vector); - return (ENXIO); - } + const char *intrstr; + char intrbuf[PCI_INTRSTR_LEN]; + char intr_xname[INTRDEVNAMEBUF]; + pci_chipset_tag_t pc = adapter->sc_pa.pa_pc; + const int irq_slot = ENA_MGMNT_IRQ_IDX; - rc = bus_activate_resource(adapter->pdev, SYS_RES_IRQ, - irq->vector, irq->res); - if (unlikely(rc != 0)) { - device_printf(adapter->pdev, "could not activate " - "irq vector: %d\n", irq->vector); - goto err_res_free; - } + KASSERT(adapter->sc_intrs != NULL); + KASSERT(adapter->sc_ihs[irq_slot] == NULL); - rc = bus_setup_intr(adapter->pdev, irq->res, - INTR_TYPE_NET | INTR_MPSAFE, NULL, ena_intr_msix_mgmnt, - irq->data, &irq->cookie); - if (unlikely(rc != 0)) { + snprintf(intr_xname, sizeof(intr_xname), "%s mgmnt", + device_xname(adapter->pdev)); + intrstr = pci_intr_string(pc, adapter->sc_intrs[irq_slot], + intrbuf, sizeof(intrbuf)); + + adapter->sc_ihs[irq_slot] = pci_intr_establish_xname( + pc, adapter->sc_intrs[irq_slot], + IPL_NET, ena_intr_msix_mgmnt, adapter, intr_xname); + + if (adapter->sc_ihs[irq_slot] == NULL) { device_printf(adapter->pdev, "failed to register " - "interrupt handler for irq %ju: %d\n", - rman_get_start(irq->res), rc); - goto err_res_free; + "interrupt handler for MGMNT irq %s\n", + intrstr); + return ENOMEM; } - irq->requested = true; - - return (rc); -err_res_free: - ena_trace(ENA_INFO | ENA_ADMQ, "releasing resource for irq %d\n", - irq->vector); - rcc = bus_release_resource(adapter->pdev, SYS_RES_IRQ, - irq->vector, irq->res); - if (unlikely(rcc != 0)) - device_printf(adapter->pdev, "dev has no parent while " - "releasing res for irq: %d\n", irq->vector); - irq->res = NULL; + aprint_normal_dev(adapter->pdev, + "for MGMNT interrupting at %s\n", intrstr); - return (rc); + return 0; } static int ena_request_io_irq(struct ena_adapter *adapter) { - struct ena_irq *irq; - unsigned long flags = 0; - int rc = 0, i, rcc; + const char *intrstr; + char intrbuf[PCI_INTRSTR_LEN]; + char intr_xname[INTRDEVNAMEBUF]; + pci_chipset_tag_t pc = adapter->sc_pa.pa_pc; + const int irq_off = ENA_IO_IRQ_FIRST_IDX; + void *vih; + kcpuset_t *affinity; + int i; - if (unlikely(adapter->msix_enabled == 0)) { - device_printf(adapter->pdev, - "failed to request I/O IRQ: MSI-X is not enabled\n"); - return (EINVAL); - } else { - flags = RF_ACTIVE | RF_SHAREABLE; - } + KASSERT(adapter->sc_intrs != NULL); - for (i = ENA_IO_IRQ_FIRST_IDX; i < adapter->msix_vecs; i++) { - irq = &adapter->irq_tbl[i]; + kcpuset_create(&affinity, false); - if (unlikely(irq->requested)) - continue; + for (i = 0; i < adapter->num_queues; i++) { + int irq_slot = i + irq_off; + int affinity_to = (irq_slot) % ncpu; - irq->res = bus_alloc_resource_any(adapter->pdev, SYS_RES_IRQ, - &irq->vector, flags); - if (unlikely(irq->res == NULL)) { - device_printf(adapter->pdev, "could not allocate " - "irq vector: %d\n", irq->vector); - goto err; - } + KASSERT((void *)adapter->sc_intrs[irq_slot] != NULL); + KASSERT(adapter->sc_ihs[irq_slot] == NULL); + + snprintf(intr_xname, sizeof(intr_xname), "%s ioq%d", + device_xname(adapter->pdev), i); + intrstr = pci_intr_string(pc, adapter->sc_intrs[irq_slot], + intrbuf, sizeof(intrbuf)); + + vih = pci_intr_establish_xname(adapter->sc_pa.pa_pc, + adapter->sc_intrs[irq_slot], IPL_NET, + ena_handle_msix, &adapter->que[i], intr_xname); - rc = bus_setup_intr(adapter->pdev, irq->res, - INTR_TYPE_NET | INTR_MPSAFE, NULL, - irq->handler, irq->data, &irq->cookie); - if (unlikely(rc != 0)) { + if (adapter->sc_ihs[ENA_MGMNT_IRQ_IDX] == NULL) { device_printf(adapter->pdev, "failed to register " - "interrupt handler for irq %ju: %d\n", - rman_get_start(irq->res), rc); + "interrupt handler for IO queue %d irq %s\n", + i, intrstr); goto err; } - irq->requested = true; + + kcpuset_zero(affinity); + /* Round-robin affinity */ + kcpuset_set(affinity, affinity_to); + int error = interrupt_distribute(vih, affinity, NULL); + if (error == 0) { + aprint_normal_dev(adapter->pdev, + "for IO queue %d interrupting at %s" + " affinity to %u\n", i, intrstr, affinity_to); + } else { + aprint_normal_dev(adapter->pdev, + "for IO queue %d interrupting at %s\n", i, intrstr); + } + + adapter->sc_ihs[irq_slot] = vih; #ifdef RSS ena_trace(ENA_INFO, "queue %d - RSS bucket %d\n", i - ENA_IO_IRQ_FIRST_IDX, irq->cpu); #else ena_trace(ENA_INFO, "queue %d - cpu %d\n", - i - ENA_IO_IRQ_FIRST_IDX, irq->cpu); + i - ENA_IO_IRQ_FIRST_IDX, affinity_to); #endif } - return (rc); + kcpuset_destroy(affinity); + return 0; err: + kcpuset_destroy(affinity); - for (; i >= ENA_IO_IRQ_FIRST_IDX; i--) { - irq = &adapter->irq_tbl[i]; - rcc = 0; - - /* Once we entered err: section and irq->requested is true we - free both intr and resources */ - if (irq->requested) - rcc = bus_teardown_intr(adapter->pdev, irq->res, irq->cookie); - if (unlikely(rcc != 0)) - device_printf(adapter->pdev, "could not release" - " irq: %d, error: %d\n", irq->vector, rcc); - - /* If we entred err: section without irq->requested set we know - it was bus_alloc_resource_any() that needs cleanup, provided - res is not NULL. In case res is NULL no work in needed in - this iteration */ - rcc = 0; - if (irq->res != NULL) { - rcc = bus_release_resource(adapter->pdev, SYS_RES_IRQ, - irq->vector, irq->res); - } - if (unlikely(rcc != 0)) - device_printf(adapter->pdev, "dev has no parent while " - "releasing res for irq: %d\n", irq->vector); - irq->requested = false; - irq->res = NULL; + for (i--; i >= 0; i--) { + int irq_slot = i + irq_off; + KASSERT(adapter->sc_ihs[irq_slot] != NULL); + pci_intr_disestablish(adapter->sc_pa.pa_pc, adapter->sc_ihs[i]); + adapter->sc_ihs[i] = NULL; } - return (rc); + return ENOSPC; } static void ena_free_mgmnt_irq(struct ena_adapter *adapter) { - struct ena_irq *irq; - int rc; - - irq = &adapter->irq_tbl[ENA_MGMNT_IRQ_IDX]; - if (irq->requested) { - ena_trace(ENA_INFO | ENA_ADMQ, "tear down irq: %d\n", - irq->vector); - rc = bus_teardown_intr(adapter->pdev, irq->res, irq->cookie); - if (unlikely(rc != 0)) - device_printf(adapter->pdev, "failed to tear " - "down irq: %d\n", irq->vector); - irq->requested = 0; - } + const int irq_slot = ENA_MGMNT_IRQ_IDX; - if (irq->res != NULL) { - ena_trace(ENA_INFO | ENA_ADMQ, "release resource irq: %d\n", - irq->vector); - rc = bus_release_resource(adapter->pdev, SYS_RES_IRQ, - irq->vector, irq->res); - irq->res = NULL; - if (unlikely(rc != 0)) - device_printf(adapter->pdev, "dev has no parent while " - "releasing res for irq: %d\n", irq->vector); + if (adapter->sc_ihs[irq_slot]) { + pci_intr_disestablish(adapter->sc_pa.pa_pc, + adapter->sc_ihs[irq_slot]); + adapter->sc_ihs[irq_slot] = NULL; } } static void ena_free_io_irq(struct ena_adapter *adapter) { - struct ena_irq *irq; - int rc; + const int irq_off = ENA_IO_IRQ_FIRST_IDX; - for (int i = ENA_IO_IRQ_FIRST_IDX; i < adapter->msix_vecs; i++) { - irq = &adapter->irq_tbl[i]; - if (irq->requested) { - ena_trace(ENA_INFO | ENA_IOQ, "tear down irq: %d\n", - irq->vector); - rc = bus_teardown_intr(adapter->pdev, irq->res, - irq->cookie); - if (unlikely(rc != 0)) { - device_printf(adapter->pdev, "failed to tear " - "down irq: %d\n", irq->vector); - } - irq->requested = 0; - } + for (int i = 0; i < adapter->num_queues; i++) { + int irq_slot = i + irq_off; - if (irq->res != NULL) { - ena_trace(ENA_INFO | ENA_IOQ, "release resource irq: %d\n", - irq->vector); - rc = bus_release_resource(adapter->pdev, SYS_RES_IRQ, - irq->vector, irq->res); - irq->res = NULL; - if (unlikely(rc != 0)) { - device_printf(adapter->pdev, "dev has no parent" - " while releasing res for irq: %d\n", - irq->vector); - } + if (adapter->sc_ihs[irq_slot]) { + pci_intr_disestablish(adapter->sc_pa.pa_pc, + adapter->sc_ihs[i]); + adapter->sc_ihs[i] = NULL; } } } @@ -2083,12 +2078,8 @@ ena_free_irqs(struct ena_adapter* adapte static void ena_disable_msix(struct ena_adapter *adapter) { - - pci_release_msi(adapter->pdev); - - adapter->msix_vecs = 0; - free(adapter->msix_entries, M_DEVBUF); - adapter->msix_entries = NULL; + pci_intr_release(adapter->sc_pa.pa_pc, adapter->sc_intrs, + adapter->sc_nintrs); } static void @@ -2160,10 +2151,12 @@ ena_up(struct ena_adapter *adapter) { int rc = 0; +#if 0 if (unlikely(device_is_attached(adapter->pdev) == 0)) { device_printf(adapter->pdev, "device is not attached!\n"); return (ENXIO); } +#endif if (unlikely(!adapter->running)) { device_printf(adapter->pdev, "device is not running!\n"); @@ -2174,7 +2167,6 @@ ena_up(struct ena_adapter *adapter) device_printf(adapter->pdev, "device is going UP\n"); /* setup interrupts for IO queues */ - ena_setup_io_intr(adapter); rc = ena_request_io_irq(adapter); if (unlikely(rc != 0)) { ena_trace(ENA_ALERT, "err_req_irq"); @@ -2214,11 +2206,11 @@ ena_up(struct ena_adapter *adapter) ena_update_hwassist(adapter); - if_setdrvflagbits(adapter->ifp, IFF_DRV_RUNNING, - IFF_DRV_OACTIVE); + if_setdrvflagbits(adapter->ifp, IFF_RUNNING, + IFF_OACTIVE); - callout_reset_sbt(&adapter->timer_service, SBT_1S, SBT_1S, - ena_timer_service, (void *)adapter, 0); + callout_reset(&adapter->timer_service, hz, + ena_timer_service, (void *)adapter); adapter->up = true; @@ -2296,16 +2288,18 @@ ena_media_status(struct ifnet *ifp, stru mutex_exit(&adapter->global_mtx); } -static void -ena_init(void *arg) +static int +ena_init(struct ifnet *ifp) { - struct ena_adapter *adapter = (struct ena_adapter *)arg; + struct ena_adapter *adapter = if_getsoftc(ifp); if (!adapter->up) { rw_enter(&adapter->ioctl_sx, RW_WRITER); ena_up(adapter); rw_exit(&adapter->ioctl_sx); } + + return 0; } static int @@ -2337,7 +2331,7 @@ ena_ioctl(struct ifnet *ifp, u_long comm case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) != 0) { - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + if ((if_getdrvflags(ifp) & IFF_RUNNING) != 0) { if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { device_printf(adapter->pdev, @@ -2349,7 +2343,7 @@ ena_ioctl(struct ifnet *ifp, u_long comm rw_exit(&adapter->ioctl_sx); } } else { - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + if ((if_getdrvflags(ifp) & IFF_RUNNING) != 0) { rw_enter(&adapter->ioctl_sx, RW_WRITER); ena_down(adapter); rw_exit(&adapter->ioctl_sx); @@ -2368,15 +2362,16 @@ ena_ioctl(struct ifnet *ifp, u_long comm case SIOCSIFCAP: { + struct ifcapreq *ifcr = data; int reinit = 0; - if (ifr->ifr_reqcap != ifp->if_capenable) { - ifp->if_capenable = ifr->ifr_reqcap; + if (ifcr->ifcr_capenable != ifp->if_capenable) { + ifp->if_capenable = ifcr->ifcr_capenable; reinit = 1; } if ((reinit != 0) && - ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0)) { + ((if_getdrvflags(ifp) & IFF_RUNNING) != 0)) { rw_enter(&adapter->ioctl_sx, RW_WRITER); ena_down(adapter); rc = ena_up(adapter); @@ -2402,31 +2397,31 @@ ena_get_dev_offloads(struct ena_com_dev_ (ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_FULL_MASK | ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK | ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L3_CSUM_IPV4_MASK)) != 0) - caps |= IFCAP_TXCSUM; + caps |= IFCAP_CSUM_IPv4_Tx; if ((feat->offload.tx & (ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_FULL_MASK | ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV6_CSUM_PART_MASK)) != 0) - caps |= IFCAP_TXCSUM_IPV6; + caps |= IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_UDPv6_Tx; if ((feat->offload.tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV4_MASK) != 0) - caps |= IFCAP_TSO4; + caps |= IFCAP_TSOv4; if ((feat->offload.tx & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TSO_IPV6_MASK) != 0) - caps |= IFCAP_TSO6; + caps |= IFCAP_TSOv6; if ((feat->offload.rx_supported & (ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV4_CSUM_MASK | ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L3_CSUM_IPV4_MASK)) != 0) - caps |= IFCAP_RXCSUM; + caps |= IFCAP_CSUM_IPv4_Rx; if ((feat->offload.rx_supported & ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK) != 0) - caps |= IFCAP_RXCSUM_IPV6; + caps |= IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx; - caps |= IFCAP_LRO | IFCAP_JUMBO_MTU; + caps |= IFCAP_LRO; return (caps); } @@ -2449,24 +2444,28 @@ ena_update_hwassist(struct ena_adapter * if_clearhwassist(ifp); - if ((cap & IFCAP_TXCSUM) != 0) { + if ((cap & (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_UDPv4_Tx)) + != 0) { if ((feat & ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L3_CSUM_IPV4_MASK) != 0) - flags |= CSUM_IP; + flags |= M_CSUM_IPv4; if ((feat & (ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_FULL_MASK | ENA_ADMIN_FEATURE_OFFLOAD_DESC_TX_L4_IPV4_CSUM_PART_MASK)) != 0) - flags |= CSUM_IP_UDP | CSUM_IP_TCP; + flags |= M_CSUM_TCPv4 | M_CSUM_UDPv4; } - if ((cap & IFCAP_TXCSUM_IPV6) != 0) - flags |= CSUM_IP6_UDP | CSUM_IP6_TCP; + if ((cap & IFCAP_CSUM_TCPv6_Tx) != 0) + flags |= M_CSUM_TCPv6; + + if ((cap & IFCAP_CSUM_UDPv6_Tx) != 0) + flags |= M_CSUM_UDPv6; - if ((cap & IFCAP_TSO4) != 0) - flags |= CSUM_IP_TSO; + if ((cap & IFCAP_TSOv4) != 0) + flags |= M_CSUM_TSOv4; - if ((cap & IFCAP_TSO6) != 0) - flags |= CSUM_IP6_TSO; + if ((cap & IFCAP_TSOv6) != 0) + flags |= M_CSUM_TSOv6; if_sethwassistbits(ifp, flags, 0); } @@ -2478,21 +2477,25 @@ ena_setup_ifnet(device_t pdev, struct en struct ifnet *ifp; int caps = 0; - ifp = adapter->ifp = if_gethandle(IFT_ETHER); + ifp = adapter->ifp = &adapter->sc_ec.ec_if; if (unlikely(ifp == NULL)) { ena_trace(ENA_ALERT, "can not allocate ifnet structure\n"); return (ENXIO); } - if_initname(ifp, device_xname(pdev), device_get_unit(pdev)); + if_initname(ifp, device_xname(pdev), device_unit(pdev)); if_setdev(ifp, pdev); if_setsoftc(ifp, adapter); if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); if_setinitfn(ifp, ena_init); if_settransmitfn(ifp, ena_mq_start); +#if 0 if_setqflushfn(ifp, ena_qflush); +#endif if_setioctlfn(ifp, ena_ioctl); +#if 0 if_setgetcounterfn(ifp, ena_get_counter); +#endif if_setsendqlen(ifp, adapter->tx_ring_size); if_setsendqready(ifp); @@ -2505,12 +2508,16 @@ ena_setup_ifnet(device_t pdev, struct en caps = ena_get_dev_offloads(feat); /* ... and set them */ if_setcapabilitiesbit(ifp, caps, 0); + adapter->sc_ec.ec_capabilities |= ETHERCAP_JUMBO_MTU; +#if 0 /* TSO parameters */ + /* XXX no limits on NetBSD, guarded by virtue of dmamap load failing */ ifp->if_hw_tsomax = ENA_TSO_MAXSIZE - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN); ifp->if_hw_tsomaxsegcount = adapter->max_tx_sgl_size - 1; ifp->if_hw_tsomaxsegsize = ENA_TSO_MAXSIZE; +#endif if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); if_setcapenable(ifp, if_getcapabilities(ifp)); @@ -2537,11 +2544,11 @@ ena_down(struct ena_adapter *adapter) if (adapter->up) { device_printf(adapter->pdev, "device is going DOWN\n"); - callout_drain(&adapter->timer_service); + callout_halt(&adapter->timer_service, &adapter->global_mtx); adapter->up = false; - if_setdrvflagbits(adapter->ifp, IFF_DRV_OACTIVE, - IFF_DRV_RUNNING); + if_setdrvflagbits(adapter->ifp, IFF_OACTIVE, + IFF_RUNNING); ena_free_io_irq(adapter); @@ -2579,12 +2586,17 @@ ena_tx_csum(struct ena_com_tx_ctx *ena_t offload = false; ena_meta = &ena_tx_ctx->ena_meta; - mss = mbuf->m_pkthdr.tso_segsz; + +#if 0 + u32 mss = mbuf->m_pkthdr.tso_segsz; if (mss != 0) offload = true; +#else + mss = mbuf->m_pkthdr.len; /* XXX don't have tso_segsz */ +#endif - if ((mbuf->m_pkthdr.csum_flags & CSUM_TSO) != 0) + if ((mbuf->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) != 0) offload = true; if ((mbuf->m_pkthdr.csum_flags & CSUM_OFFLOAD) != 0) @@ -2601,7 +2613,7 @@ ena_tx_csum(struct ena_com_tx_ctx *ena_t etype = ntohs(eh->evl_proto); ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; } else { - etype = ntohs(eh->evl_encap_proto); + etype = htons(eh->evl_encap_proto); ehdrlen = ETHER_HDR_LEN; } @@ -2609,10 +2621,10 @@ ena_tx_csum(struct ena_com_tx_ctx *ena_t iphlen = ip->ip_hl << 2; th = (struct tcphdr *)((vaddr_t)ip + iphlen); - if ((mbuf->m_pkthdr.csum_flags & CSUM_IP) != 0) { + if ((mbuf->m_pkthdr.csum_flags & M_CSUM_IPv4) != 0) { ena_tx_ctx->l3_csum_enable = 1; } - if ((mbuf->m_pkthdr.csum_flags & CSUM_TSO) != 0) { + if ((mbuf->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) != 0) { ena_tx_ctx->tso_enable = 1; ena_meta->l4_hdr_len = (th->th_off); } @@ -2633,14 +2645,14 @@ ena_tx_csum(struct ena_com_tx_ctx *ena_t if (ip->ip_p == IPPROTO_TCP) { ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_TCP; if ((mbuf->m_pkthdr.csum_flags & - (CSUM_IP_TCP | CSUM_IP6_TCP)) != 0) + (M_CSUM_TCPv4 | M_CSUM_TCPv6)) != 0) ena_tx_ctx->l4_csum_enable = 1; else ena_tx_ctx->l4_csum_enable = 0; } else if (ip->ip_p == IPPROTO_UDP) { ena_tx_ctx->l4_proto = ENA_ETH_IO_L4_PROTO_UDP; if ((mbuf->m_pkthdr.csum_flags & - (CSUM_IP_UDP | CSUM_IP6_UDP)) != 0) + (M_CSUM_UDPv4 | M_CSUM_UDPv6)) != 0) ena_tx_ctx->l4_csum_enable = 1; else ena_tx_ctx->l4_csum_enable = 0; @@ -2692,13 +2704,11 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, struct ena_com_dev *ena_dev; struct ena_com_buf *ena_buf; struct ena_com_io_sq* io_sq; - bus_dma_segment_t segs[ENA_BUS_DMA_SEGS]; void *push_hdr; uint16_t next_to_use; uint16_t req_id; - uint16_t push_len; uint16_t ena_qid; - uint32_t nsegs, header_len; + uint32_t header_len; int i, rc; int nb_hw_desc; @@ -2725,7 +2735,6 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, ena_trace(ENA_DBG | ENA_TXPTH, "Tx: %d bytes", (*mbuf)->m_pkthdr.len); - push_len = 0; /* * header_len is just a hint for the device. Because FreeBSD is not * giving us information about packet header length and it is not @@ -2736,12 +2745,13 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, header_len = 0; push_hdr = NULL; - rc = bus_dmamap_load_mbuf_sg(adapter->sc_dmat, tx_info->map, - *mbuf, segs, &nsegs, BUS_DMA_NOWAIT); + rc = bus_dmamap_load_mbuf(adapter->sc_dmat, tx_info->map, + *mbuf, BUS_DMA_NOWAIT); - if (unlikely((rc != 0) || (nsegs == 0))) { + if (unlikely((rc != 0) || (tx_info->map->dm_nsegs == 0))) { ena_trace(ENA_WARNING, - "dmamap load failed! err: %d nsegs: %d", rc, nsegs); + "dmamap load failed! err: %d nsegs: %d", rc, + tx_info->map->dm_nsegs); counter_u64_add(tx_ring->tx_stats.dma_mapping_err, 1); tx_info->mbuf = NULL; if (rc == ENOMEM) @@ -2750,12 +2760,12 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, return (ENA_COM_INVAL); } - for (i = 0; i < nsegs; i++) { - ena_buf->len = segs[i].ds_len; - ena_buf->paddr = segs[i].ds_addr; + for (i = 0; i < tx_info->map->dm_nsegs; i++) { + ena_buf->len = tx_info->map->dm_segs[i].ds_len; + ena_buf->paddr = tx_info->map->dm_segs[i].ds_addr; ena_buf++; } - tx_info->num_of_bufs = nsegs; + tx_info->num_of_bufs = tx_info->map->dm_nsegs; memset(&ena_tx_ctx, 0x0, sizeof(struct ena_com_tx_ctx)); ena_tx_ctx.ena_bufs = tx_info->bufs; @@ -2791,8 +2801,8 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use, tx_ring->ring_size); - bus_dmamap_sync(adapter->sc_dmat, tx_info->map, - BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(adapter->sc_dmat, tx_info->map, 0, + tx_info->map->dm_mapsize, BUS_DMASYNC_PREWRITE); return (0); @@ -2813,7 +2823,7 @@ ena_start_xmit(struct ena_ring *tx_ring) int acum_pkts = 0; int ret = 0; - if (unlikely((if_getdrvflags(adapter->ifp) & IFF_DRV_RUNNING) == 0)) + if (unlikely((if_getdrvflags(adapter->ifp) & IFF_RUNNING) == 0)) return; if (unlikely(!adapter->link_status)) @@ -2847,12 +2857,16 @@ ena_start_xmit(struct ena_ring *tx_ring) drbr_advance(adapter->ifp, tx_ring->br); if (unlikely((if_getdrvflags(adapter->ifp) & - IFF_DRV_RUNNING) == 0)) + IFF_RUNNING) == 0)) return; acum_pkts++; - BPF_MTAP(adapter->ifp, mbuf); + /* + * If there's a BPF listener, bounce a copy of this frame + * to him. + */ + bpf_mtap(adapter->ifp, mbuf); /* XXX already in if_input? */ if (unlikely(acum_pkts == DB_THRESHOLD)) { acum_pkts = 0; @@ -2876,13 +2890,13 @@ ena_start_xmit(struct ena_ring *tx_ring) } static void -ena_deferred_mq_start(void *arg, int pending) +ena_deferred_mq_start(struct work *wk, void *arg) { struct ena_ring *tx_ring = (struct ena_ring *)arg; struct ifnet *ifp = tx_ring->adapter->ifp; while (!drbr_empty(ifp, tx_ring->br) && - (if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + (if_getdrvflags(ifp) & IFF_RUNNING) != 0) { ENA_RING_MTX_LOCK(tx_ring); ena_start_xmit(tx_ring); ENA_RING_MTX_UNLOCK(tx_ring); @@ -2897,7 +2911,7 @@ ena_mq_start(struct ifnet *ifp, struct m int ret, is_drbr_empty; uint32_t i; - if (unlikely((if_getdrvflags(adapter->ifp) & IFF_DRV_RUNNING) == 0)) + if (unlikely((if_getdrvflags(adapter->ifp) & IFF_RUNNING) == 0)) return (ENODEV); /* Which queue to use */ @@ -2906,6 +2920,7 @@ ena_mq_start(struct ifnet *ifp, struct m * same bucket that the current CPU we're on is. * It should improve performance. */ +#if 0 if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { #ifdef RSS if (rss_hash2bucket(m->m_pkthdr.flowid, @@ -2918,15 +2933,19 @@ ena_mq_start(struct ifnet *ifp, struct m i = m->m_pkthdr.flowid % adapter->num_queues; } } else { - i = curcpu % adapter->num_queues; +#endif + i = cpu_index(curcpu()) % adapter->num_queues; +#if 0 } +#endif tx_ring = &adapter->tx_ring[i]; /* Check if drbr is empty before putting packet */ is_drbr_empty = drbr_empty(ifp, tx_ring->br); ret = drbr_enqueue(ifp, tx_ring->br, m); if (unlikely(ret != 0)) { - taskqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task); + workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task, + curcpu()); return (ret); } @@ -2934,12 +2953,14 @@ ena_mq_start(struct ifnet *ifp, struct m ena_start_xmit(tx_ring); ENA_RING_MTX_UNLOCK(tx_ring); } else { - taskqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task); + workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task, + curcpu()); } return (0); } +#if 0 static void ena_qflush(struct ifnet *ifp) { @@ -2956,9 +2977,11 @@ ena_qflush(struct ifnet *ifp) if_qflush(ifp); } +#endif static int -ena_calc_io_queue_num(struct ena_adapter *adapter, +ena_calc_io_queue_num(struct pci_attach_args *pa, + struct ena_adapter *adapter, struct ena_com_dev_get_features_ctx *get_feat_ctx) { int io_sq_num, io_cq_num, io_queue_num; @@ -2971,7 +2994,7 @@ ena_calc_io_queue_num(struct ena_adapter io_queue_num = min_t(int, io_queue_num, io_cq_num); /* 1 IRQ for for mgmnt and 1 IRQ for each TX/RX pair */ io_queue_num = min_t(int, io_queue_num, - pci_msix_count(adapter->pdev) - 1); + pci_msix_count(pa->pa_pc, pa->pa_tag) - 1); #ifdef RSS io_queue_num = min_t(int, io_queue_num, rss_getnumbuckets()); #endif @@ -3018,6 +3041,7 @@ ena_calc_queue_size(struct ena_adapter * return (queue_size); } +#if 0 static int ena_rss_init_default(struct ena_adapter *adapter) { @@ -3096,6 +3120,7 @@ ena_rss_init_default_deferred(void *arg) } } SYSINIT(ena_rss_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_SECOND, ena_rss_init_default_deferred, NULL); +#endif static void ena_config_host_info(struct ena_com_dev *ena_dev) @@ -3162,7 +3187,8 @@ ena_device_init(struct ena_adapter *adap * The PCIe configuration space revision id indicate if mmio reg * read is disabled */ - readless_supported = !(pci_get_revid(pdev) & ENA_MMIO_DISABLE_REG_READ); + const int rev = PCI_REVISION(adapter->sc_pa.pa_class); + readless_supported = ((rev & ENA_MMIO_DISABLE_REG_READ) == 0); ena_com_set_mmio_read_mode(ena_dev, readless_supported); rc = ena_com_dev_reset(ena_dev, ENA_REGS_RESET_NORMAL); @@ -3244,8 +3270,6 @@ static int ena_enable_msix_and_set_admin return (rc); } - ena_setup_mgmnt_intr(adapter); - rc = ena_request_mgmnt_irq(adapter); if (unlikely(rc != 0)) { device_printf(adapter->pdev, "Cannot setup mgmnt queue intr\n"); @@ -3280,7 +3304,7 @@ static void ena_keep_alive_wd(void *adap counter_u64_add(adapter->hw_stats.rx_drops, rx_drops); stime = getsbinuptime(); - atomic_store_rel_64(&adapter->keep_alive_timestamp, stime); + (void) atomic_swap_64(&adapter->keep_alive_timestamp, stime); } /* Check for keep alive expiration */ @@ -3294,7 +3318,10 @@ static void check_for_missing_keep_alive if (likely(adapter->keep_alive_timeout == 0)) return; - timestamp = atomic_load_acq_64(&adapter->keep_alive_timestamp); + /* FreeBSD uses atomic_load_acq_64() in place of the membar + read */ + membar_sync(); + timestamp = adapter->keep_alive_timestamp; + time = getsbinuptime() - timestamp; if (unlikely(time > adapter->keep_alive_timeout)) { device_printf(adapter->pdev, @@ -3449,8 +3476,8 @@ check_for_empty_rx_ring(struct ena_adapt device_printf(adapter->pdev, "trigger refill for ring %d\n", i); - taskqueue_enqueue(rx_ring->cmpl_tq, - &rx_ring->cmpl_task); + workqueue_enqueue(rx_ring->cmpl_tq, + &rx_ring->cmpl_task, curcpu()); rx_ring->empty_rx_queue = 0; } } else { @@ -3479,18 +3506,19 @@ ena_timer_service(void *data) if (unlikely(adapter->trigger_reset)) { device_printf(adapter->pdev, "Trigger reset is on\n"); - taskqueue_enqueue(adapter->reset_tq, &adapter->reset_task); + workqueue_enqueue(adapter->reset_tq, &adapter->reset_task, + curcpu()); return; } /* * Schedule another timeout one second from now. */ - callout_schedule_sbt(&adapter->timer_service, SBT_1S, SBT_1S, 0); + callout_schedule(&adapter->timer_service, hz); } static void -ena_reset_task(void *arg, int pending) +ena_reset_task(struct work *wk, void *arg) { struct ena_com_dev_get_features_ctx get_feat_ctx; struct ena_adapter *adapter = (struct ena_adapter *)arg; @@ -3506,7 +3534,7 @@ ena_reset_task(void *arg, int pending) rw_enter(&adapter->ioctl_sx, RW_WRITER); - callout_drain(&adapter->timer_service); + callout_halt(&adapter->timer_service, &adapter->global_mtx); dev_up = adapter->up; @@ -3531,6 +3559,7 @@ ena_reset_task(void *arg, int pending) goto err_dev_free; } + /* XXX dealloc and realloc MSI-X, probably a waste */ rc = ena_enable_msix_and_set_admin_interrupts(adapter, adapter->num_queues); if (unlikely(rc != 0)) { @@ -3548,8 +3577,8 @@ ena_reset_task(void *arg, int pending) } } - callout_reset_sbt(&adapter->timer_service, SBT_1S, SBT_1S, - ena_timer_service, (void *)adapter, 0); + callout_reset(&adapter->timer_service, hz, + ena_timer_service, (void *)adapter); rw_exit(&adapter->ioctl_sx); @@ -3576,7 +3605,7 @@ err_dev_free: * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int +static void ena_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa = aux; @@ -3593,6 +3622,7 @@ ena_attach(device_t parent, device_t sel adapter->pdev = self; adapter->ifp = &adapter->sc_ec.ec_if; + adapter->sc_pa = *pa; /* used after attach for adapter reset too */ if (pci_dma64_available(pa)) adapter->sc_dmat = pa->pa_dmat64; @@ -3611,7 +3641,6 @@ ena_attach(device_t parent, device_t sel rw_init(&adapter->ioctl_sx); /* Set up the timer service */ - callout_init_mtx(&adapter->timer_service, &adapter->global_mtx, 0); adapter->keep_alive_timeout = DEFAULT_KEEP_ALIVE_TO; adapter->missing_tx_timeout = DEFAULT_TX_CMP_TO; adapter->missing_tx_max_queues = DEFAULT_TX_MONITORED_QUEUES; @@ -3620,11 +3649,11 @@ ena_attach(device_t parent, device_t sel if (version_printed++ == 0) device_printf(parent, "%s\n", ena_version); - rc = ena_allocate_pci_resources(adapter); + rc = ena_allocate_pci_resources(pa, adapter); if (unlikely(rc != 0)) { device_printf(parent, "PCI resource allocation failed!\n"); ena_free_pci_resources(adapter); - return (rc); + return; } /* Allocate memory for ena_dev structure */ @@ -3637,23 +3666,15 @@ ena_attach(device_t parent, device_t sel M_WAITOK | M_ZERO); /* Store register resources */ - ((struct ena_bus*)(ena_dev->bus))->reg_bar_t = - rman_get_bustag(adapter->registers); - ((struct ena_bus*)(ena_dev->bus))->reg_bar_h = - rman_get_bushandle(adapter->registers); - - if (unlikely(((struct ena_bus*)(ena_dev->bus))->reg_bar_h == 0)) { - device_printf(pdev, "failed to pmap registers bar\n"); - rc = ENXIO; - goto err_bus_free; - } + ((struct ena_bus*)(ena_dev->bus))->reg_bar_t = adapter->sc_btag; + ((struct ena_bus*)(ena_dev->bus))->reg_bar_h = adapter->sc_bhandle; ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; /* Device initialization */ - rc = ena_device_init(adapter, pdev, &get_feat_ctx, &adapter->wd_active); + rc = ena_device_init(adapter, self, &get_feat_ctx, &adapter->wd_active); if (unlikely(rc != 0)) { - device_printf(pdev, "ENA device init failed! (err: %d)\n", rc); + device_printf(self, "ENA device init failed! (err: %d)\n", rc); rc = ENXIO; goto err_bus_free; } @@ -3669,7 +3690,7 @@ ena_attach(device_t parent, device_t sel ETHER_ADDR_LEN); /* calculate IO queue number to create */ - io_queue_num = ena_calc_io_queue_num(adapter, &get_feat_ctx); + io_queue_num = ena_calc_io_queue_num(pa, adapter, &get_feat_ctx); ENA_ASSERT(io_queue_num > 0, "Invalid queue number: %d\n", io_queue_num); @@ -3693,65 +3714,71 @@ ena_attach(device_t parent, device_t sel adapter->max_tx_sgl_size = tx_sgl_size; adapter->max_rx_sgl_size = rx_sgl_size; +#if 0 /* set up dma tags for rx and tx buffers */ rc = ena_setup_tx_dma_tag(adapter); if (unlikely(rc != 0)) { - device_printf(pdev, "Failed to create TX DMA tag\n"); + device_printf(self, "Failed to create TX DMA tag\n"); goto err_com_free; } rc = ena_setup_rx_dma_tag(adapter); if (unlikely(rc != 0)) { - device_printf(pdev, "Failed to create RX DMA tag\n"); + device_printf(self, "Failed to create RX DMA tag\n"); goto err_tx_tag_free; } +#endif /* initialize rings basic information */ - device_printf(pdev, "initalize %d io queues\n", io_queue_num); + device_printf(self, "initalize %d io queues\n", io_queue_num); ena_init_io_rings(adapter); /* setup network interface */ - rc = ena_setup_ifnet(pdev, adapter, &get_feat_ctx); + rc = ena_setup_ifnet(self, adapter, &get_feat_ctx); if (unlikely(rc != 0)) { - device_printf(pdev, "Error with network interface setup\n"); + device_printf(self, "Error with network interface setup\n"); goto err_io_free; } rc = ena_enable_msix_and_set_admin_interrupts(adapter, io_queue_num); if (unlikely(rc != 0)) { - device_printf(pdev, + device_printf(self, "Failed to enable and set the admin interrupts\n"); goto err_ifp_free; } /* Initialize reset task queue */ - TASK_INIT(&adapter->reset_task, 0, ena_reset_task, adapter); - adapter->reset_tq = taskqueue_create("ena_reset_enqueue", - M_WAITOK | M_ZERO, taskqueue_thread_enqueue, &adapter->reset_tq); - taskqueue_start_threads(&adapter->reset_tq, 1, IPL_NET, - "%s rstq", device_xname(adapter->pdev)); + rc = workqueue_create(&adapter->reset_tq, "ena_reset_enqueue", + ena_reset_task, adapter, 0, IPL_NET, 0); + if (unlikely(rc != 0)) { + ena_trace(ENA_ALERT, + "Unable to create workqueue for reset task\n"); + goto err_ifp_free; + } /* Initialize statistics */ - ena_alloc_counters((struct evcnt *)&adapter->dev_stats, - sizeof(struct ena_stats_dev)); - ena_alloc_counters((struct evcnt *)&adapter->hw_stats, - sizeof(struct ena_hw_stats)); + ena_alloc_counters_dev(&adapter->dev_stats, io_queue_num); + ena_alloc_counters_hwstats(&adapter->hw_stats, io_queue_num); +#if 0 ena_sysctl_add_nodes(adapter); +#endif /* Tell the stack that the interface is not active */ - if_setdrvflagbits(adapter->ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); + if_setdrvflagbits(adapter->ifp, IFF_OACTIVE, IFF_RUNNING); adapter->running = true; - return (0); + return; err_ifp_free: if_detach(adapter->ifp); if_free(adapter->ifp); err_io_free: ena_free_all_io_rings_resources(adapter); +#if 0 ena_free_rx_dma_tag(adapter); err_tx_tag_free: ena_free_tx_dma_tag(adapter); +#endif err_com_free: ena_com_admin_destroy(ena_dev); ena_com_delete_host_info(ena_dev); @@ -3760,8 +3787,6 @@ err_bus_free: free(ena_dev->bus, M_DEVBUF); free(ena_dev, M_DEVBUF); ena_free_pci_resources(adapter); - - return (rc); } /** @@ -3772,23 +3797,25 @@ err_bus_free: * that it should release a PCI device. **/ static int -ena_detach(device_t pdev) +ena_detach(device_t pdev, int flags) { struct ena_adapter *adapter = device_private(pdev); struct ena_com_dev *ena_dev = adapter->ena_dev; +#if 0 int rc; +#endif /* Make sure VLANS are not using driver */ - if (adapter->ifp->if_vlantrunk != NULL) { + if (VLAN_ATTACHED(&adapter->sc_ec)) { device_printf(adapter->pdev ,"VLAN is in use, detach first\n"); return (EBUSY); } /* Free reset task and callout */ - callout_drain(&adapter->timer_service); - while (taskqueue_cancel(adapter->reset_tq, &adapter->reset_task, NULL)) - taskqueue_drain(adapter->reset_tq, &adapter->reset_task); - taskqueue_free(adapter->reset_tq); + callout_halt(&adapter->timer_service, &adapter->global_mtx); + workqueue_wait(adapter->reset_tq, &adapter->reset_task); + workqueue_destroy(adapter->reset_tq); + adapter->reset_tq = NULL; rw_enter(&adapter->ioctl_sx, RW_WRITER); ena_down(adapter); @@ -3809,6 +3836,7 @@ ena_detach(device_t pdev) if (likely(adapter->rss_support)) ena_com_rss_destroy(ena_dev); +#if 0 rc = ena_free_rx_dma_tag(adapter); if (unlikely(rc != 0)) device_printf(adapter->pdev, @@ -3818,6 +3846,7 @@ ena_detach(device_t pdev) if (unlikely(rc != 0)) device_printf(adapter->pdev, "Unmapped TX DMA tag associations\n"); +#endif /* Reset the device only if the device is running. */ if (adapter->running) @@ -3846,7 +3875,7 @@ ena_detach(device_t pdev) if (ena_dev != NULL) free(ena_dev, M_DEVBUF); - return (bus_generic_detach(pdev)); + return 0; } /****************************************************************************** @@ -3926,3 +3955,8 @@ MODULE_DEPEND(ena, ether, 1, 1, 1); /*********************************************************************/ #endif /* __FreeBSD__ */ + +#ifdef __NetBSD__ +CFATTACH_DECL_NEW(ena, sizeof(struct ena_adapter), ena_probe, ena_attach, + ena_detach, NULL); +#endif /* __NetBSD */ Index: src/sys/dev/pci/if_enavar.h diff -u src/sys/dev/pci/if_enavar.h:1.2 src/sys/dev/pci/if_enavar.h:1.3 --- src/sys/dev/pci/if_enavar.h:1.2 Sat May 19 09:32:55 2018 +++ src/sys/dev/pci/if_enavar.h Sat Jun 16 15:00:35 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_enavar.h,v 1.2 2018/05/19 09:32:55 jdolecek Exp $ */ +/* $NetBSD: if_enavar.h,v 1.3 2018/06/16 15:00:35 jdolecek Exp $ */ /*- * BSD LICENSE @@ -147,6 +147,8 @@ #define PCI_DEV_ID_ENA_VF 0xec20 #define PCI_DEV_ID_ENA_LLQ_VF 0xec21 +typedef __int64_t sbintime_t; + struct msix_entry { int entry; int vector; @@ -158,18 +160,6 @@ typedef struct _ena_vendor_info_t { unsigned int index; } ena_vendor_info_t; -struct ena_irq { - /* Interrupt resources */ - struct resource *res; - void *handler; - void *data; - void *cookie; - unsigned int vector; - bool requested; - int cpu; - char name[ENA_IRQNAME_SIZE]; -}; - struct ena_que { struct ena_adapter *adapter; struct ena_ring *tx_ring; @@ -201,6 +191,7 @@ struct ena_rx_buffer { } __aligned(CACHE_LINE_SIZE); struct ena_stats_tx { + char name[16]; struct evcnt cnt; struct evcnt bytes; struct evcnt prepare_ctx_err; @@ -213,6 +204,7 @@ struct ena_stats_tx { }; struct ena_stats_rx { + char name[16]; struct evcnt cnt; struct evcnt bytes; struct evcnt refil_partial; @@ -291,6 +283,7 @@ struct ena_ring { } __aligned(CACHE_LINE_SIZE); struct ena_stats_dev { + char name[16]; struct evcnt wd_expired; struct evcnt interface_up; struct evcnt interface_down; @@ -298,6 +291,7 @@ struct ena_stats_dev { }; struct ena_hw_stats { + char name[16]; struct evcnt rx_packets; struct evcnt tx_packets; @@ -318,16 +312,17 @@ struct ena_adapter { struct ifmedia media; /* OS resources */ - struct resource *memory; - struct resource *registers; - kmutex_t global_mtx; krwlock_t ioctl_sx; - /* MSI-X */ - uint32_t msix_enabled; - struct msix_entry *msix_entries; - int msix_vecs; + void *sc_ihs[ENA_MAX_MSIX_VEC(ENA_MAX_NUM_IO_QUEUES)]; + pci_intr_handle_t *sc_intrs; + int sc_nintrs; + struct pci_attach_args sc_pa; + + /* Registers */ + bus_space_handle_t sc_bhandle; + bus_space_tag_t sc_btag; /* DMA tag used throughout the driver adapter for Tx and Rx */ bus_dma_tag_t sc_dmat; @@ -370,17 +365,15 @@ struct ena_adapter { struct ena_ring rx_ring[ENA_MAX_NUM_IO_QUEUES] __aligned(CACHE_LINE_SIZE); - struct ena_irq irq_tbl[ENA_MAX_MSIX_VEC(ENA_MAX_NUM_IO_QUEUES)]; - /* Timer service */ struct callout timer_service; - struct bintime keep_alive_timestamp; + sbintime_t keep_alive_timestamp; uint32_t next_monitored_tx_qid; struct work reset_task; struct workqueue *reset_tq; int wd_active; - struct bintime keep_alive_timeout; - struct bintime missing_tx_timeout; + sbintime_t keep_alive_timeout; + sbintime_t missing_tx_timeout; uint32_t missing_tx_max_queues; uint32_t missing_tx_threshold; @@ -405,4 +398,90 @@ static inline int ena_mbuf_count(struct return count; } +/* provide FreeBSD-compatible macros */ +#define if_getcapenable(ifp) (ifp)->if_capenable +#define if_setcapenable(ifp, s) SET((ifp)->if_capenable, s) +#define if_getcapabilities(ifp) (ifp)->if_capabilities +#define if_setcapabilities(ifp, s) SET((ifp)->if_capabilities, s) +#define if_setcapabilitiesbit(ifp, s, c) do { \ + CLR((ifp)->if_capabilities, c); \ + SET((ifp)->if_capabilities, s); \ + } while (0) +#define if_getsoftc(ifp) (ifp)->if_softc +#define if_setmtu(ifp, new_mtu) (ifp)->if_mtu = (new_mtu) +#define if_getdrvflags(ifp) (ifp)->if_flags +#define if_setdrvflagbits(ifp, s, c) do { \ + CLR((ifp)->if_flags, c); \ + SET((ifp)->if_flags, s); \ + } while (0) +#define if_setflags(ifp, s) SET((ifp)->if_flags, s) +#define if_sethwassistbits(ifp, s, c) do { \ + CLR((ifp)->if_csum_flags_rx, c); \ + SET((ifp)->if_csum_flags_rx, s); \ + } while (0) +#define if_clearhwassist(ifp) (ifp)->if_csum_flags_rx = 0 +#define if_setbaudrate(ifp, r) (ifp)->if_baudrate = (r) +#define if_setdev(ifp, dev) do { } while (0) +#define if_setsoftc(ifp, softc) (ifp)->if_softc = (softc) +#define if_setinitfn(ifp, initfn) (ifp)->if_init = (initfn) +#define if_settransmitfn(ifp, txfn) (ifp)->if_transmit = (txfn) +#define if_setioctlfn(ifp, ioctlfn) (ifp)->if_ioctl = (ioctlfn) +#define if_setsendqlen(ifp, sqlen) \ + IFQ_SET_MAXLEN(&(ifp)->if_snd, max(sqlen, IFQ_MAXLEN)) +#define if_setsendqready(ifp) IFQ_SET_READY(&(ifp)->if_snd) +#define if_setifheaderlen(ifp, len) (ifp)->if_hdrlen = (len) + +#define SBT_1S ((sbintime_t)1 << 32) +#define bintime_clear(a) ((a)->sec = (a)->frac = 0) +#define bintime_isset(a) ((a)->sec || (a)->frac) + +static __inline sbintime_t +bttosbt(const struct bintime _bt) +{ + return (((sbintime_t)_bt.sec << 32) + (_bt.frac >> 32)); +} + +static __inline sbintime_t +getsbinuptime(void) +{ + struct bintime _bt; + + getbinuptime(&_bt); + return (bttosbt(_bt)); +} + +/* Intentionally non-atomic, it's just unnecessary overhead */ +#define counter_u64_add(x, cnt) (x).ev_count += (cnt) +#define counter_u64_zero(x) (x).ev_count = 0 +#define counter_u64_free(x) evcnt_detach(&(x)) + +#define counter_u64_add_protected(x, cnt) (x).ev_count += (cnt) +#define counter_enter() do {} while (0) +#define counter_exit() do {} while (0) + +/* Misc other constants */ +#define mp_ncpus ncpu +#define osreldate __NetBSD_Version__ + +/* + * XXX XXX XXX just to make compile, must provide replacement XXX XXX XXX + * Other than that, TODO: + * - decide whether to import <sys/buf_ring.h> + * - recheck the M_CSUM/IPCAP mapping + * - recheck workqueue use - FreeBSD taskqueues might have different semantics + */ +#define buf_ring_alloc(a, b, c, d) (void *)&a +#define drbr_free(ifp, b) do { } while (0) +#define drbr_flush(ifp, b) do { } while (0) +#define drbr_advance(ifp, b) do { } while (0) +#define drbr_putback(ifp, b, m) do { } while (0) +#define drbr_empty(ifp, b) false +#define drbr_peek(ifp, b) NULL +#define drbr_enqueue(ifp, b, m) 0 +#define m_getjcl(a, b, c, d) NULL +#define MJUM16BYTES MCLBYTES +#define m_append(m, len, cp) 0 +#define m_collapse(m, how, maxfrags) NULL +/* XXX XXX XXX */ + #endif /* !(ENA_H) */ Index: src/sys/external/bsd/ena-com/ena_plat.h diff -u src/sys/external/bsd/ena-com/ena_plat.h:1.2 src/sys/external/bsd/ena-com/ena_plat.h:1.3 --- src/sys/external/bsd/ena-com/ena_plat.h:1.2 Sat May 19 08:59:38 2018 +++ src/sys/external/bsd/ena-com/ena_plat.h Sat Jun 16 15:00:35 2018 @@ -38,7 +38,7 @@ #if 0 __FBSDID("$FreeBSD: head/sys/contrib/ena-com/ena_plat.h 333453 2018-05-10 09:25:51Z mw $"); #endif -__KERNEL_RCSID(0, "$NetBSD: ena_plat.h,v 1.2 2018/05/19 08:59:38 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ena_plat.h,v 1.3 2018/06/16 15:00:35 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -324,7 +324,7 @@ int ena_dma_alloc(device_t dmadev, bus_s #define time_after(a,b) ((long)((unsigned long)(b) - (unsigned long)(a)) < 0) #define VLAN_HLEN sizeof(struct ether_vlan_header) -#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP) +#define CSUM_OFFLOAD (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4) #if defined(__i386__) || defined(__amd64__) static __inline