Module Name:    src
Committed By:   jmcneill
Date:           Mon Jul 19 21:16:33 UTC 2021

Modified Files:
        src/sys/dev/pci: if_ena.c if_enavar.h
        src/sys/external/bsd/ena-com: ena_plat.h

Log Message:
Various ena(4) bug fixes, from KUSABA Takeshi <t-kus...@iij.ad.jp>:

[PATCH 01/32] include device_xname for evcnt group.
[PATCH 02/32] fix improper NULL check.
[PATCH 03/32] add tx drop counter
[PATCH 04/32] remove unimplemented m_getjcl
[PATCH 05/32] make ENA_MEM_{ALLOC,FREE}_COHERENT symmetric.
[PATCH 06/32] disestablish the correct interrupt.
[PATCH 07/32] fix null check target.
[PATCH 08/32] use if_initialize() and if_register() instead of
[PATCH 09/32] free all pci-related resource.
[PATCH 10/32] no need to call if_free(), but to call if_detach
[PATCH 11/32] add some locking assertions.
[PATCH 12/32] use bus_size_t for bus_dma instead of uint32_t.
[PATCH 13/32] no need to pass interlock, ena_timer_service does not
[PATCH 14/32] enable ena(4) to down I/F
[PATCH 15/32] destroy I/O queues before disestablishing msix
[PATCH 16/32] count input/output packet stats.
[PATCH 17/32] fix missing #ifdef LRO, NetBSD does not support LRO
[PATCH 18/32] MP-ify TX, allocate mbuf queue to each TX ring.
[PATCH 19/32] down the interface first when to detach, to prevent
[PATCH 20/32] default link speed should be unknown.
[PATCH 21/32] protect ena_adapter members only by "global_mtx".
[PATCH 22/32] lower global_mtx interrupt level
[PATCH 23/32] reorder function declaration
[PATCH 24/32] add locking notes and some marking.
[PATCH 25/32] process RX in workqueue context, as same as FreeBSD
[PATCH 26/32] count rx_drops correctly.
[PATCH 27/32] no need to lock when attach/detach, down/up
[PATCH 28/32] fix memory leak.
[PATCH 29/32] add "stopping" flag to ena_ring.
[PATCH 30/32] make the flags atomic.
[PATCH 31/32] do not schedule timer when device is down.
[PATCH 32/32] no need to start timer if I/F is down.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/pci/if_ena.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/if_enavar.h
cvs rdiff -u -r1.6 -r1.7 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.28 src/sys/dev/pci/if_ena.c:1.29
--- src/sys/dev/pci/if_ena.c:1.28	Thu Jul  1 17:22:10 2021
+++ src/sys/dev/pci/if_ena.c	Mon Jul 19 21:16:33 2021
@@ -36,7 +36,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.28 2021/07/01 17:22:10 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1.29 2021/07/19 21:16:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,112 +72,154 @@ __KERNEL_RCSID(0, "$NetBSD: if_ena.c,v 1
 /*********************************************************
  *  Function prototypes
  *********************************************************/
+/* cfattach interface functions */
 static int	ena_probe(device_t, cfdata_t, void *);
-static int	ena_intr_msix_mgmnt(void *);
+static void	ena_attach(device_t, device_t, void *);
+static int	ena_detach(device_t, int);
+
+/* ifnet interface functions */
+static int	ena_init(struct ifnet *);
+static void	ena_stop(struct ifnet *, int);
+static int	ena_ioctl(struct ifnet *, u_long, void *);
+static int	ena_media_change(struct ifnet *);
+static void	ena_media_status(struct ifnet *, struct ifmediareq *);
+static int	ena_mq_start(struct ifnet *, struct mbuf *);
+
+/* attach or detach */
+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 *);
+
 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 void	ena_free_irqs(struct ena_adapter*);
+
 static void	ena_init_io_rings_common(struct ena_adapter *,
-    struct ena_ring *, uint16_t);
+                                            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 *);
-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_get_dev_offloads(struct ena_com_dev_get_features_ctx *);
+static int	ena_setup_ifnet(device_t, struct ena_adapter *,
+		    struct ena_com_dev_get_features_ctx *);
+
+static inline void	ena_alloc_counters_rx(struct ena_adapter *,
+			    struct ena_stats_rx *, int);
+static inline void	ena_alloc_counters_tx(struct ena_adapter *,
+			    struct ena_stats_tx *, int);
+static inline void	ena_alloc_counters_dev(struct ena_adapter *,
+			    struct ena_stats_dev *, int);
+static inline void	ena_alloc_counters_hwstats(struct ena_adapter *,
+			    struct ena_hw_stats *, int);
+static inline void	ena_free_counters(struct evcnt *, int, int);
+
+/* attach or detach or ena_reset_task() */
+static void	ena_reset_task(struct work *, void *);
+
+static void	ena_free_mgmnt_irq(struct ena_adapter *);
+static void	ena_disable_msix(struct ena_adapter *);
+static void	ena_config_host_info(struct ena_com_dev *);
+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 int	ena_enable_msix(struct ena_adapter *);
+static int	ena_request_mgmnt_irq(struct ena_adapter *);
+
+/* I/F up or down */
+static int	ena_up_complete(struct ena_adapter *);
+static int	ena_up(struct ena_adapter *);
+static void	ena_down(struct ena_adapter *);
+static void	ena_set_stopping_flag(struct ena_adapter *, bool);
+
 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_rx_resources(struct ena_adapter *, unsigned int);
 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);
+		    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 int	ena_setup_tx_resources(struct ena_adapter *, int);
+static int	ena_setup_all_tx_resources(struct ena_adapter *);
+static void	ena_free_tx_resources(struct ena_adapter *, int);
+static void	ena_free_all_tx_resources(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 int	ena_request_io_irq(struct ena_adapter *);
+static void	ena_free_io_irq(struct ena_adapter *);
+static int	ena_create_io_queues(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(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 int	ena_handle_msix(void *);
-static int	ena_enable_msix(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 *);
-#if 0
-static uint64_t	ena_get_counter(struct ifnet *, ift_counter);
-#endif
-static int	ena_media_change(struct ifnet *);
-static void	ena_media_status(struct ifnet *, struct ifmediareq *);
-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 *);
+
 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_rss_configure(struct ena_adapter *);
+static void	ena_unmask_all_io_irqs(struct ena_adapter *);
+static inline void	ena_reset_counters(struct evcnt *, int, int);
+
+/* other hardware interrupt, workqueue, softint context */
+static int	ena_intr_msix_mgmnt(void *);
+static void	ena_update_on_link_change(void *,
+		    struct ena_admin_aenq_entry *);
+static void	ena_keep_alive_wd(void *,
+		    struct ena_admin_aenq_entry *);
+static void	unimplemented_aenq_handler(void *,
+		    struct ena_admin_aenq_entry *);
+
+static int	ena_handle_msix(void *);
+static void	ena_cleanup(struct work *, void *);
+static inline int	validate_rx_req_id(struct ena_ring *, uint16_t);
+static inline int	ena_alloc_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_refill_all_rx_bufs(struct ena_adapter *);
+static int	ena_rx_cleanup(struct ena_ring *);
+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 int	ena_check_and_collapse_mbuf(struct ena_ring *tx_ring,
-    struct mbuf **mbuf);
+		    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(struct ifnet *, struct mbuf *);
 static void	ena_deferred_mq_start(struct work *, void *);
+static int	ena_tx_cleanup(struct ena_ring *);
+static void	ena_tx_csum(struct ena_com_tx_ctx *, struct mbuf *);
+static inline int	validate_tx_req_id(struct ena_ring *, uint16_t);
+
+/* other */
+static int	ena_change_mtu(struct ifnet *, int);
+
+static void	ena_timer_service(void *);
+static void	check_for_missing_keep_alive(struct ena_adapter *);
+static void	check_for_admin_com_state(struct ena_adapter *);
+static int	check_missing_comp_in_queue(struct ena_adapter *, struct ena_ring*);
+static void	check_for_missing_tx_completions(struct ena_adapter *);
+static void	check_for_empty_rx_ring(struct ena_adapter *);
+static void	ena_update_host_info(struct ena_admin_host_info *,
+		    struct ifnet *);
+
 #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 *);
+static void	ena_rx_hash_mbuf(struct ena_ring *, struct ena_com_rx_ctx *,
+    struct mbuf *);
+static uint64_t	ena_get_counter(struct ifnet *, ift_counter);
 static void	ena_qflush(struct ifnet *);
-#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 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 *,
-    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 const char ena_version[] =
     DEVICE_NAME DRV_MODULE_NAME " v" DRV_MODULE_VERSION;
@@ -223,9 +265,8 @@ ena_dma_alloc(device_t dmadev, bus_size_
     ena_mem_handle_t *dma , int mapflags)
 {
 	struct ena_adapter *adapter = device_private(dmadev);
-	uint32_t maxsize;
-	bus_dma_segment_t seg;
-	int error, nsegs;
+	bus_size_t maxsize;
+	int error;
 
 	maxsize = ((size - 1) / PAGE_SIZE + 1) * PAGE_SIZE;
 
@@ -245,7 +286,7 @@ ena_dma_alloc(device_t dmadev, bus_size_
                 goto fail_create;
 	}
 
-	error = bus_dmamem_alloc(dma->tag, maxsize, 8, 0, &seg, 1, &nsegs,
+	error = bus_dmamem_alloc(dma->tag, maxsize, 8, 0, &dma->seg, 1, &dma->nseg,
 	    BUS_DMA_ALLOCNOW);
 	if (error) {
 		ena_trace(ENA_ALERT, "bus_dmamem_alloc(%ju) failed: %d\n",
@@ -253,7 +294,7 @@ ena_dma_alloc(device_t dmadev, bus_size_
 		goto fail_alloc;
 	}
 
-	error = bus_dmamem_map(dma->tag, &seg, nsegs, maxsize,
+	error = bus_dmamem_map(dma->tag, &dma->seg, dma->nseg, maxsize,
 	    &dma->vaddr, BUS_DMA_COHERENT);
 	if (error) {
 		ena_trace(ENA_ALERT, "bus_dmamem_map(%ju) failed: %d\n",
@@ -275,7 +316,7 @@ ena_dma_alloc(device_t dmadev, bus_size_
 fail_load:
 	bus_dmamem_unmap(dma->tag, dma->vaddr, maxsize);
 fail_map:
-	bus_dmamem_free(dma->tag, &seg, nsegs);
+	bus_dmamem_free(dma->tag, &dma->seg, dma->nseg);
 fail_alloc:
 	bus_dmamap_destroy(adapter->sc_dmat, dma->map);
 fail_create:
@@ -287,8 +328,6 @@ ena_allocate_pci_resources(struct pci_at
     struct ena_adapter *adapter)
 {
 	pcireg_t memtype, reg;
-	bus_addr_t memaddr;
-	bus_size_t mapsize;
 	int flags, error;
 	int msixoff;
 
@@ -312,7 +351,7 @@ ena_allocate_pci_resources(struct pci_at
 
 	adapter->sc_btag = pa->pa_memt;
 	error = pci_mapreg_info(pa->pa_pc, pa->pa_tag, ENA_REG_BAR,
-	    memtype, &memaddr, &mapsize, &flags);
+	    memtype, &adapter->sc_memaddr, &adapter->sc_mapsize, &flags);
 	if (error) {
 		aprint_error_dev(adapter->pdev, "can't get map info\n");
 		return ENXIO;
@@ -321,7 +360,7 @@ ena_allocate_pci_resources(struct pci_at
 	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, &msixoff,
 	    NULL)) {
 		pcireg_t msixtbl;
-		uint32_t table_offset;
+		bus_size_t table_offset;
 		int bir;
 
 		msixtbl = pci_conf_read(pa->pa_pc, pa->pa_tag,
@@ -329,11 +368,11 @@ ena_allocate_pci_resources(struct pci_at
 		table_offset = msixtbl & PCI_MSIX_TBLOFFSET_MASK;
 		bir = msixtbl & PCI_MSIX_TBLBIR_MASK;
 		if (bir == PCI_MAPREG_NUM(ENA_REG_BAR))
-			mapsize = table_offset;
+			adapter->sc_mapsize = table_offset;
 	}
 
-	error = bus_space_map(adapter->sc_btag, memaddr, mapsize, flags,
-	    &adapter->sc_bhandle);
+	error = bus_space_map(adapter->sc_btag, adapter->sc_memaddr,
+	    adapter->sc_mapsize, flags, &adapter->sc_bhandle);
 	if (error != 0) {
 		aprint_error_dev(adapter->pdev,
 		    "can't map mem space (error=%d)\n", error);
@@ -346,7 +385,10 @@ ena_allocate_pci_resources(struct pci_at
 static void
 ena_free_pci_resources(struct ena_adapter *adapter)
 {
-	/* Nothing to do */
+	if (adapter->sc_mapsize != 0) {
+		bus_space_unmap(adapter->sc_btag, adapter->sc_bhandle,
+		    adapter->sc_mapsize);
+	}
 }
 
 static int
@@ -399,15 +441,15 @@ ena_change_mtu(struct ifnet *ifp, int ne
 	} while (0)
 
 static inline void
-ena_alloc_counters_rx(struct ena_stats_rx *st, int queue)
+ena_alloc_counters_rx(struct ena_adapter *adapter, struct ena_stats_rx *st, int queue)
 {
-	snprintf(st->name, sizeof(st->name), "ena rxq%d", queue);
+	snprintf(st->name, sizeof(st->name), "%s rxq%d",
+	    device_xname(adapter->pdev), queue);
 
 	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);
@@ -420,9 +462,10 @@ ena_alloc_counters_rx(struct ena_stats_r
 }
 
 static inline void
-ena_alloc_counters_tx(struct ena_stats_tx *st, int queue)
+ena_alloc_counters_tx(struct ena_adapter *adapter, struct ena_stats_tx *st, int queue)
 {
-	snprintf(st->name, sizeof(st->name), "ena txq%d", queue);
+	snprintf(st->name, sizeof(st->name), "%s txq%d",
+	    device_xname(adapter->pdev), queue);
 
 	EVCNT_INIT(st, cnt);
 	EVCNT_INIT(st, bytes);
@@ -433,16 +476,18 @@ ena_alloc_counters_tx(struct ena_stats_t
 	EVCNT_INIT(st, bad_req_id);
 	EVCNT_INIT(st, collapse);
 	EVCNT_INIT(st, collapse_err);
+	EVCNT_INIT(st, pcq_drops);
 
 	/* Make sure all code is updated when new fields added */
-	CTASSERT(offsetof(struct ena_stats_tx, collapse_err)
-	    + sizeof(st->collapse_err) == sizeof(*st));
+	CTASSERT(offsetof(struct ena_stats_tx, pcq_drops)
+	    + sizeof(st->pcq_drops) == sizeof(*st));
 }
 
 static inline void
-ena_alloc_counters_dev(struct ena_stats_dev *st, int queue)
+ena_alloc_counters_dev(struct ena_adapter *adapter, struct ena_stats_dev *st, int queue)
 {
-	snprintf(st->name, sizeof(st->name), "ena dev ioq%d", queue);
+	snprintf(st->name, sizeof(st->name), "%s dev ioq%d",
+	    device_xname(adapter->pdev), queue);
 
 	EVCNT_INIT(st, wd_expired);
 	EVCNT_INIT(st, interface_up);
@@ -455,9 +500,10 @@ ena_alloc_counters_dev(struct ena_stats_
 }
 
 static inline void
-ena_alloc_counters_hwstats(struct ena_hw_stats *st, int queue)
+ena_alloc_counters_hwstats(struct ena_adapter *adapter, struct ena_hw_stats *st, int queue)
 {
-	snprintf(st->name, sizeof(st->name), "ena hw ioq%d", queue);
+	snprintf(st->name, sizeof(st->name), "%s hw ioq%d",
+	    device_xname(adapter->pdev), queue);
 
 	EVCNT_INIT(st, rx_packets);
 	EVCNT_INIT(st, tx_packets);
@@ -529,7 +575,7 @@ ena_init_io_rings(struct ena_adapter *ad
 		    M_WAITOK, &txr->ring_mtx);
 
 		/* Alloc TX statistics. */
-		ena_alloc_counters_tx(&txr->tx_stats, i);
+		ena_alloc_counters_tx(adapter, &txr->tx_stats, i);
 
 		/* RX specific ring state */
 		rxr->ring_size = adapter->rx_ring_size;
@@ -537,7 +583,7 @@ ena_init_io_rings(struct ena_adapter *ad
 		    ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
 
 		/* Alloc RX statistics. */
-		ena_alloc_counters_rx(&rxr->rx_stats, i);
+		ena_alloc_counters_rx(adapter, &rxr->rx_stats, i);
 
 		/* Initialize locks */
 		snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
@@ -572,10 +618,6 @@ ena_free_io_ring_resources(struct ena_ad
 	ena_free_counters((struct evcnt *)&rxr->rx_stats,
 	    sizeof(rxr->rx_stats), offsetof(struct ena_stats_rx, cnt));
 
-	ENA_RING_MTX_LOCK(txr);
-	drbr_free(txr->br, M_DEVBUF);
-	ENA_RING_MTX_UNLOCK(txr);
-
 	mutex_destroy(&txr->ring_mtx);
 	mutex_destroy(&rxr->ring_mtx);
 }
@@ -673,10 +715,7 @@ ena_setup_tx_resources(struct ena_adapte
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 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);
+	tx_ring->br = pcq_create(ENA_DEFAULT_RING_SIZE, KM_SLEEP);
 
 	/* ... and create the buffer DMA maps */
 	for (i = 0; i < tx_ring->ring_size; i++) {
@@ -740,14 +779,17 @@ static void
 ena_free_tx_resources(struct ena_adapter *adapter, int qid)
 {
 	struct ena_ring *tx_ring = &adapter->tx_ring[qid];
+	struct mbuf *m;
 
 	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, */
-	drbr_flush(adapter->ifp, tx_ring->br);
+	while ((m = pcq_get(tx_ring->br)) != NULL)
+		m_freem(m);
+	pcq_destroy(tx_ring->br);
+	tx_ring->br = NULL;
 
 	/* Free buffer DMA maps, */
 	for (int i = 0; i < tx_ring->ring_size; i++) {
@@ -758,7 +800,6 @@ ena_free_tx_resources(struct ena_adapter
 		bus_dmamap_destroy(adapter->sc_dmat,
 		    tx_ring->tx_buffer_info[i].map);
 	}
-	ENA_RING_MTX_UNLOCK(tx_ring);
 
 	/* And free allocated memory. */
 	free(tx_ring->tx_buffer_info, M_DEVBUF);
@@ -824,7 +865,7 @@ validate_rx_req_id(struct ena_ring *rx_r
 
 	/* Trigger device reset */
 	rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
-	rx_ring->adapter->trigger_reset = true;
+	ENA_FLAG_SET_ATOMIC(ENA_FLAG_TRIGGER_RESET, rx_ring->adapter);
 
 	return (EFAULT);
 }
@@ -899,8 +940,8 @@ ena_setup_rx_resources(struct ena_adapte
 #endif
 
 	/* Allocate workqueues */
-	int rc = workqueue_create(&rx_ring->cmpl_tq, "ena_rx_comp",
-	    ena_deferred_rx_cleanup, rx_ring, 0, IPL_NET, WQ_PERCPU | WQ_FLAGS);
+	int rc = workqueue_create(&rx_ring->cleanup_tq, "ena_rx_comp",
+	    ena_cleanup, que, 0, IPL_NET, WQ_PERCPU | WQ_FLAGS);
 	if (unlikely(rc != 0)) {
 		ena_trace(ENA_ALERT,
 		    "Unable to create workqueue for RX completion task\n");
@@ -947,9 +988,9 @@ ena_free_rx_resources(struct ena_adapter
 {
 	struct ena_ring *rx_ring = &adapter->rx_ring[qid];
 
-	workqueue_wait(rx_ring->cmpl_tq, &rx_ring->cmpl_task);
-	workqueue_destroy(rx_ring->cmpl_tq);
-	rx_ring->cmpl_tq = NULL;
+	workqueue_wait(rx_ring->cleanup_tq, &rx_ring->cleanup_task);
+	workqueue_destroy(rx_ring->cleanup_tq);
+	rx_ring->cleanup_tq = NULL;
 
 	/* Free buffer DMA maps, */
 	for (int i = 0; i < rx_ring->ring_size; i++) {
@@ -1029,20 +1070,13 @@ ena_alloc_rx_mbuf(struct ena_adapter *ad
 	if (unlikely(rx_info->mbuf != NULL))
 		return (0);
 
-	/* Get mbuf using UMA allocator */
-	rx_info->mbuf = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM16BYTES);
-
+	rx_info->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 	if (unlikely(rx_info->mbuf == NULL)) {
-		counter_u64_add(rx_ring->rx_stats.mjum_alloc_fail, 1);
-		rx_info->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
-		if (unlikely(rx_info->mbuf == NULL)) {
-			counter_u64_add(rx_ring->rx_stats.mbuf_alloc_fail, 1);
-			return (ENOMEM);
-		}
-		mlen = MCLBYTES;
-	} else {
-		mlen = MJUM16BYTES;
+		counter_u64_add(rx_ring->rx_stats.mbuf_alloc_fail, 1);
+		return (ENOMEM);
 	}
+	mlen = MCLBYTES;
+
 	/* Set mbuf length*/
 	rx_info->mbuf->m_pkthdr.len = rx_info->mbuf->m_len = mlen;
 
@@ -1216,7 +1250,6 @@ ena_free_tx_bufs(struct ena_adapter *ada
 	bool print_once = true;
 	struct ena_ring *tx_ring = &adapter->tx_ring[qid];
 
-	ENA_RING_MTX_LOCK(tx_ring);
 	for (int i = 0; i < tx_ring->ring_size; i++) {
 		struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
 
@@ -1238,7 +1271,6 @@ ena_free_tx_bufs(struct ena_adapter *ada
 		m_free(tx_info->mbuf);
 		tx_info->mbuf = NULL;
 	}
-	ENA_RING_MTX_UNLOCK(tx_ring);
 }
 
 static void
@@ -1285,6 +1317,7 @@ validate_tx_req_id(struct ena_ring *tx_r
 {
 	struct ena_adapter *adapter = tx_ring->adapter;
 	struct ena_tx_buffer *tx_info = NULL;
+	KASSERT(ENA_RING_MTX_OWNED(tx_ring));
 
 	if (likely(req_id < tx_ring->ring_size)) {
 		tx_info = &tx_ring->tx_buffer_info[req_id];
@@ -1408,6 +1441,8 @@ ena_tx_cleanup(struct ena_ring *tx_ring)
 	int budget = TX_BUDGET;
 	int work_done;
 
+	KASSERT(ENA_RING_MTX_OWNED(tx_ring));
+
 	adapter = tx_ring->que->adapter;
 	ena_qid = ENA_IO_TXQ_IDX(tx_ring->que->id);
 	io_cq = &adapter->ena_dev->io_cq_queues[ena_qid];
@@ -1553,17 +1588,15 @@ ena_rx_mbuf(struct ena_ring *rx_ring, st
 
 	ntc = *next_to_clean;
 	adapter = rx_ring->adapter;
-	rx_info = &rx_ring->rx_buffer_info[ntc];
 
+	len = ena_bufs[buf].len;
+	req_id = ena_bufs[buf].req_id;
+	rx_info = &rx_ring->rx_buffer_info[req_id];
 	if (unlikely(rx_info->mbuf == NULL)) {
 		device_printf(adapter->pdev, "NULL mbuf in rx_info");
 		return (NULL);
 	}
 
-	len = ena_bufs[buf].len;
-	req_id = ena_bufs[buf].req_id;
-	rx_info = &rx_ring->rx_buffer_info[req_id];
-
 	ena_trace(ENA_DBG | ENA_RXPTH, "rx_info %p, mbuf %p, paddr %jx",
 	    rx_info, rx_info->mbuf, (uintmax_t)rx_info->ena_buf.paddr);
 
@@ -1684,26 +1717,6 @@ ena_rx_checksum(struct ena_ring *rx_ring
 	}
 }
 
-static void
-ena_deferred_rx_cleanup(struct work *wk, void *arg)
-{
-	struct ena_ring *rx_ring = arg;
-	int budget = CLEAN_BUDGET;
-
-	atomic_swap_uint(&rx_ring->task_pending, 0);
-
-	ENA_RING_MTX_LOCK(rx_ring);
-	/*
-	 * If deferred task was executed, perform cleanup of all awaiting
-	 * descs (or until given budget is depleted to avoid infinite loop).
-	 */
-	while (likely(budget--)) {
-		if (ena_rx_cleanup(rx_ring) == 0)
-			break;
-	}
-	ENA_RING_MTX_UNLOCK(rx_ring);
-}
-
 /**
  * ena_rx_cleanup - handle rx irq
  * @arg: ring for which irq is being handled
@@ -1767,6 +1780,7 @@ ena_rx_cleanup(struct ena_ring *rx_ring)
 				    rx_ring->ring_size);
 
 			}
+			if_statinc(ifp, if_ierrors);
 			break;
 		}
 
@@ -1853,7 +1867,7 @@ ena_intr_msix_mgmnt(void *arg)
 	struct ena_adapter *adapter = (struct ena_adapter *)arg;
 
 	ena_com_admin_q_comp_intr_handler(adapter->ena_dev);
-	if (likely(adapter->running))
+	if (likely(ENA_FLAG_ISSET(ENA_FLAG_DEVICE_RUNNING, adapter)))
 		ena_com_aenq_intr_handler(adapter->ena_dev, arg);
 
 	return 1;
@@ -1866,23 +1880,43 @@ ena_intr_msix_mgmnt(void *arg)
 static int
 ena_handle_msix(void *arg)
 {
+	struct ena_que *queue = arg;
+	struct ena_ring *rx_ring = queue->rx_ring;
+
+	ENA_RING_MTX_LOCK(rx_ring);
+	if (unlikely(rx_ring->stopping)) {
+		ENA_RING_MTX_UNLOCK(rx_ring);
+		return 0;
+	}
+
+	if (atomic_cas_uint(&rx_ring->task_pending, 0, 1) == 0)
+		workqueue_enqueue(rx_ring->cleanup_tq, &rx_ring->cleanup_task,
+		    curcpu());
+
+	ENA_RING_MTX_UNLOCK(rx_ring);
+	return 1;
+}
+
+static void
+ena_cleanup(struct work *wk, void *arg)
+{
 	struct ena_que	*que = arg;
 	struct ena_adapter *adapter = que->adapter;
 	struct ifnet *ifp = adapter->ifp;
-	struct ena_ring *tx_ring;
-	struct ena_ring *rx_ring;
+	struct ena_ring *tx_ring = que->tx_ring;
+	struct ena_ring *rx_ring = que->rx_ring;
 	struct ena_com_io_cq* io_cq;
 	struct ena_eth_io_intr_reg intr_reg;
 	int qid, ena_qid;
 	int txc, rxc, i;
 
+	atomic_swap_uint(&rx_ring->task_pending, 0);
+
 	if (unlikely((if_getdrvflags(ifp) & IFF_RUNNING) == 0))
-		return 0;
+		return;
 
 	ena_trace(ENA_DBG, "MSI-X TX/RX routine");
 
-	tx_ring = que->tx_ring;
-	rx_ring = que->rx_ring;
 	qid = que->id;
 	ena_qid = ENA_IO_TXQ_IDX(qid);
 	io_cq = &adapter->ena_dev->io_cq_queues[ena_qid];
@@ -1893,20 +1927,25 @@ ena_handle_msix(void *arg)
 		 * being executed and rx ring is being cleaned up in
 		 * another thread.
 		 */
-		if (likely(ENA_RING_MTX_TRYLOCK(rx_ring) != 0)) {
-			rxc = ena_rx_cleanup(rx_ring);
+		ENA_RING_MTX_LOCK(rx_ring);
+		if (rx_ring->stopping) {
 			ENA_RING_MTX_UNLOCK(rx_ring);
-		} else {
-			rxc = 0;
+			return;
 		}
+		ENA_RING_MTX_UNLOCK(rx_ring);
+		rxc = ena_rx_cleanup(rx_ring);
 
 		/* Protection from calling ena_tx_cleanup from ena_start_xmit */
 		ENA_RING_MTX_LOCK(tx_ring);
+		if (tx_ring->stopping) {
+			ENA_RING_MTX_UNLOCK(tx_ring);
+			return;
+		}
 		txc = ena_tx_cleanup(tx_ring);
 		ENA_RING_MTX_UNLOCK(tx_ring);
 
 		if (unlikely((if_getdrvflags(ifp) & IFF_RUNNING) == 0))
-			return 0;
+			return;
 
 		if ((txc != TX_BUDGET) && (rxc != RX_BUDGET))
 		       break;
@@ -1918,8 +1957,6 @@ ena_handle_msix(void *arg)
 	    TX_IRQ_INTERVAL,
 	    true);
 	ena_com_unmask_intr(io_cq, &intr_reg);
-
-	return 1;
 }
 
 static int
@@ -2058,7 +2095,7 @@ ena_request_io_irq(struct ena_adapter *a
 		    adapter->sc_intrs[irq_slot], IPL_NET,
 		    ena_handle_msix, &adapter->que[i], intr_xname);
 
-		if (adapter->sc_ihs[ENA_MGMNT_IRQ_IDX] == NULL) {
+		if (vih == NULL) {
 			device_printf(adapter->pdev, "failed to register "
 			    "interrupt handler for IO queue %d irq %s\n",
 			    i, intrstr);
@@ -2098,8 +2135,8 @@ err:
 	for (i--; i >= 0; i--) {
 		int irq_slot __diagused = 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;
+		pci_intr_disestablish(adapter->sc_pa.pa_pc, adapter->sc_ihs[irq_slot]);
+		adapter->sc_ihs[irq_slot] = NULL;
 	}
 
 	return ENOSPC;
@@ -2127,8 +2164,8 @@ ena_free_io_irq(struct ena_adapter *adap
 
 		if (adapter->sc_ihs[irq_slot]) {
 			pci_intr_disestablish(adapter->sc_pa.pa_pc,
-			    adapter->sc_ihs[i]);
-			adapter->sc_ihs[i] = NULL;
+			    adapter->sc_ihs[irq_slot]);
+			adapter->sc_ihs[irq_slot] = NULL;
 		}
 	}
 }
@@ -2219,6 +2256,8 @@ ena_up(struct ena_adapter *adapter)
 {
 	int rc = 0;
 
+	KASSERT(ENA_CORE_MTX_OWNED(adapter));
+
 #if 0
 	if (unlikely(device_is_attached(adapter->pdev) == 0)) {
 		device_printf(adapter->pdev, "device is not attached!\n");
@@ -2226,12 +2265,12 @@ ena_up(struct ena_adapter *adapter)
 	}
 #endif
 
-	if (unlikely(!adapter->running)) {
+	if (unlikely(!ENA_FLAG_ISSET(ENA_FLAG_DEVICE_RUNNING, adapter))) {
 		device_printf(adapter->pdev, "device is not running!\n");
 		return (ENXIO);
 	}
 
-	if (!adapter->up) {
+	if (!ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter)) {
 		device_printf(adapter->pdev, "device is going UP\n");
 
 		/* setup interrupts for IO queues */
@@ -2263,7 +2302,7 @@ ena_up(struct ena_adapter *adapter)
 			goto err_io_que;
 		}
 
-		if (unlikely(adapter->link_status))
+		if (unlikely(ENA_FLAG_ISSET(ENA_FLAG_LINK_UP, adapter)))
 			if_link_state_change(adapter->ifp, LINK_STATE_UP);
 
 		rc = ena_up_complete(adapter);
@@ -2276,10 +2315,11 @@ ena_up(struct ena_adapter *adapter)
 
 		if_setdrvflagbits(adapter->ifp, IFF_RUNNING,
 		    IFF_OACTIVE);
+		ena_set_stopping_flag(adapter, false);
 
 		callout_schedule(&adapter->timer_service, hz);
 
-		adapter->up = true;
+		ENA_FLAG_SET_ATOMIC(ENA_FLAG_DEV_UP, adapter);
 
 		ena_unmask_all_io_irqs(adapter);
 	}
@@ -2338,21 +2378,17 @@ ena_media_status(struct ifnet *ifp, stru
 	struct ena_adapter *adapter = if_getsoftc(ifp);
 	ena_trace(ENA_DBG, "enter");
 
-	mutex_enter(&adapter->global_mtx);
+	KASSERT(ENA_CORE_MTX_OWNED(adapter));
 
 	ifmr->ifm_status = IFM_AVALID;
 	ifmr->ifm_active = IFM_ETHER;
 
-	if (!adapter->link_status) {
-		mutex_exit(&adapter->global_mtx);
-		ena_trace(ENA_INFO, "link_status = false");
+	if (!ENA_FLAG_ISSET(ENA_FLAG_LINK_UP, adapter)) {
+		ena_trace(ENA_INFO, "Link is down");
 		return;
 	}
 
 	ifmr->ifm_status |= IFM_ACTIVE;
-	ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
-
-	mutex_exit(&adapter->global_mtx);
 }
 
 static int
@@ -2360,15 +2396,29 @@ ena_init(struct ifnet *ifp)
 {
 	struct ena_adapter *adapter = if_getsoftc(ifp);
 
-	if (!adapter->up) {
-		rw_enter(&adapter->ioctl_sx, RW_WRITER);
+	if (!ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter)) {
+		ENA_CORE_MTX_LOCK(adapter);
 		ena_up(adapter);
-		rw_exit(&adapter->ioctl_sx);
+		ENA_CORE_MTX_UNLOCK(adapter);
 	}
 
 	return 0;
 }
 
+static void
+ena_stop(struct ifnet *ifp, int disable){
+	struct ena_adapter *adapter;
+
+	adapter = ifp->if_softc;
+
+	if (ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter)) {
+		ENA_CORE_MTX_LOCK(adapter);
+		ena_down(adapter);
+		ENA_CORE_MTX_UNLOCK(adapter);
+	}
+}
+
+
 static int
 ena_ioctl(struct ifnet *ifp, u_long command, void *data)
 {
@@ -2387,13 +2437,13 @@ ena_ioctl(struct ifnet *ifp, u_long comm
 	case SIOCSIFMTU:
 		if (ifp->if_mtu == ifr->ifr_mtu)
 			break;
-		rw_enter(&adapter->ioctl_sx, RW_WRITER);
+		ENA_CORE_MTX_LOCK(adapter);
 		ena_down(adapter);
 
 		ena_change_mtu(ifp, ifr->ifr_mtu);
 
 		rc = ena_up(adapter);
-		rw_exit(&adapter->ioctl_sx);
+		ENA_CORE_MTX_UNLOCK(adapter);
 		break;
 
 	case SIOCADDMULTI:
@@ -2412,10 +2462,10 @@ ena_ioctl(struct ifnet *ifp, u_long comm
 
 			if ((reinit != 0) &&
 			    ((if_getdrvflags(ifp) & IFF_RUNNING) != 0)) {
-				rw_enter(&adapter->ioctl_sx, RW_WRITER);
+				ENA_CORE_MTX_LOCK(adapter);
 				ena_down(adapter);
 				rc = ena_up(adapter);
-				rw_exit(&adapter->ioctl_sx);
+				ENA_CORE_MTX_UNLOCK(adapter);
 			}
 		}
 
@@ -2461,7 +2511,9 @@ ena_get_dev_offloads(struct ena_com_dev_
 	    ENA_ADMIN_FEATURE_OFFLOAD_DESC_RX_L4_IPV6_CSUM_MASK) != 0)
 		caps |= IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
 
+#ifdef LRO
 	caps |= IFCAP_LRO;
+#endif
 
 	return (caps);
 }
@@ -2522,12 +2574,14 @@ ena_setup_ifnet(device_t pdev, struct en
 		ena_trace(ENA_ALERT, "can not allocate ifnet structure\n");
 		return (ENXIO);
 	}
+	if_initialize(ifp);
 	if_initname(ifp, "ena", 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);
+	ifp->if_stop = ena_stop;
 	if_settransmitfn(ifp, ena_mq_start);
 #if 0
 	if_setqflushfn(ifp, ena_qflush);
@@ -2567,36 +2621,63 @@ ena_setup_ifnet(device_t pdev, struct en
 	 * callbacks to update media and link information
 	 */
 	adapter->sc_ec.ec_ifmedia = &adapter->media;
-	ifmedia_init(&adapter->media, IFM_IMASK,
-	    ena_media_change, ena_media_status);
+	ifmedia_init_with_lock(&adapter->media, IFM_IMASK,
+	    ena_media_change, ena_media_status, &adapter->global_mtx);
 	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
 
-	if_attach(ifp);
+	ifp->if_percpuq = if_percpuq_create(ifp);
 	if_deferred_start_init(ifp, NULL);
-
 	ether_ifattach(ifp, adapter->mac_addr);
+	if_register(ifp);
 
 	return (0);
 }
 
 static void
-ena_down(struct ena_adapter *adapter)
+ena_set_stopping_flag(struct ena_adapter *adapter, bool value)
 {
-	int rc;
+	struct ena_ring *ring;
+	int i;
 
-	if (adapter->up) {
-		device_printf(adapter->pdev, "device is going DOWN\n");
+	for (i = 0; i < adapter->num_queues; i++) {
+		/* TX */
+		ring = adapter->que[i].tx_ring;
+		ENA_RING_MTX_LOCK(ring);
+		ring->stopping = value;
+		ENA_RING_MTX_UNLOCK(ring);
+
+		/* RX */
+		ring = adapter->que[i].rx_ring;
+		ENA_RING_MTX_LOCK(ring);
+		ring->stopping = value;
+		ENA_RING_MTX_UNLOCK(ring);
+	}
+}
 
-		callout_halt(&adapter->timer_service, &adapter->global_mtx);
+static void
+ena_down(struct ena_adapter *adapter)
+{
+	int rc, i;
 
-		adapter->up = false;
+	KASSERT(ENA_CORE_MTX_OWNED(adapter));
+
+	if (ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter)) {
+		device_printf(adapter->pdev, "device is going DOWN\n");
+		ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_DEV_UP, adapter);
 		if_setdrvflagbits(adapter->ifp, IFF_OACTIVE,
 		    IFF_RUNNING);
 
-		ena_free_io_irq(adapter);
+		ena_set_stopping_flag(adapter, true);
+
+		callout_halt(&adapter->timer_service, NULL);
+		for (i = 0; i < adapter->num_queues; i++) {
+			struct ena_ring *rx_ring = adapter->que[i].rx_ring;
+			workqueue_wait(rx_ring->cleanup_tq,
+			    &rx_ring->cleanup_task);
+		}
 
-		if (adapter->trigger_reset) {
+		if (ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter)) {
 			rc = ena_com_dev_reset(adapter->ena_dev,
 			    adapter->reset_reason);
 			if (unlikely(rc != 0))
@@ -2611,6 +2692,8 @@ ena_down(struct ena_adapter *adapter)
 		ena_free_all_tx_resources(adapter);
 		ena_free_all_rx_resources(adapter);
 
+		ena_free_io_irq(adapter);
+
 		counter_u64_add(adapter->dev_stats.interface_down, 1);
 	}
 }
@@ -2756,6 +2839,8 @@ ena_xmit_mbuf(struct ena_ring *tx_ring, 
 	int i, rc;
 	int nb_hw_desc;
 
+	KASSERT(ENA_RING_MTX_OWNED(tx_ring));
+
 	ena_qid = ENA_IO_TXQ_IDX(tx_ring->que->id);
 	adapter = tx_ring->que->adapter;
 	ena_dev = adapter->ena_dev;
@@ -2866,17 +2951,23 @@ ena_start_xmit(struct ena_ring *tx_ring)
 	int ena_qid;
 	int acum_pkts = 0;
 	int ret = 0;
+	net_stat_ref_t nsr;
 
+	KASSERT(ENA_RING_MTX_OWNED(tx_ring));
+
+	/* ena_down() is waiting for completing */
 	if (unlikely((if_getdrvflags(adapter->ifp) & IFF_RUNNING) == 0))
 		return;
 
-	if (unlikely(!adapter->link_status))
+	if (unlikely(!ENA_FLAG_ISSET(ENA_FLAG_LINK_UP, adapter)))
 		return;
 
 	ena_qid = ENA_IO_TXQ_IDX(tx_ring->que->id);
 	io_sq = &adapter->ena_dev->io_sq_queues[ena_qid];
 
-	while ((mbuf = drbr_peek(adapter->ifp, tx_ring->br)) != NULL) {
+	nsr = IF_STAT_GETREF(adapter->ifp);
+
+	while ((mbuf = pcq_get(tx_ring->br)) != NULL) {
 		ena_trace(ENA_DBG | ENA_TXPTH, "\ndequeued mbuf %p with flags %#x and"
 		    " header csum flags %#jx",
 		    mbuf, mbuf->m_flags, (uint64_t)mbuf->m_pkthdr.csum_flags);
@@ -2885,24 +2976,32 @@ ena_start_xmit(struct ena_ring *tx_ring)
 		    ENA_TX_CLEANUP_THRESHOLD)))
 			ena_tx_cleanup(tx_ring);
 
-		if (unlikely((ret = ena_xmit_mbuf(tx_ring, &mbuf)) != 0)) {
-			if (ret == ENA_COM_NO_MEM) {
-				drbr_putback(adapter->ifp, tx_ring->br, mbuf);
-			} else if (ret == ENA_COM_NO_SPACE) {
-				drbr_putback(adapter->ifp, tx_ring->br, mbuf);
+		if (likely((ret = ena_xmit_mbuf(tx_ring, &mbuf)) == 0)) {
+			if_statinc_ref(nsr, if_opackets);
+			if_statadd_ref(nsr, if_obytes, mbuf->m_pkthdr.len);
+			if (ISSET(mbuf->m_flags, M_MCAST))
+				if_statinc_ref(nsr, if_omcasts);
+		} else {
+			if_statinc_ref(nsr, if_oerrors);
+			/*
+			 * Since mbuf is restructured in ena_xmit_mbuf(),
+			 * we re-put mbuf.
+			 */
+			if (ret == ENA_COM_NO_MEM || ret == ENA_COM_NO_SPACE) {
+				pcq_put(tx_ring->br, mbuf);
 			} else {
 				m_freem(mbuf);
-				drbr_advance(adapter->ifp, tx_ring->br);
 			}
 
 			break;
 		}
 
-		drbr_advance(adapter->ifp, tx_ring->br);
-
+		/* ena_down is waiting for completing */
 		if (unlikely((if_getdrvflags(adapter->ifp) &
-		    IFF_RUNNING) == 0))
+		    IFF_RUNNING) == 0)) {
+			IF_STAT_PUTREF(adapter->ifp);
 			return;
+		}
 
 		acum_pkts++;
 
@@ -2922,6 +3021,8 @@ ena_start_xmit(struct ena_ring *tx_ring)
 
 	}
 
+	IF_STAT_PUTREF(adapter->ifp);
+
 	if (likely(acum_pkts != 0)) {
 		wmb();
 		/* Trigger the dma engine */
@@ -2941,9 +3042,13 @@ ena_deferred_mq_start(struct work *wk, v
 
 	atomic_swap_uint(&tx_ring->task_pending, 0);
 
-	while (!drbr_empty(ifp, tx_ring->br) &&
+	while (pcq_peek(tx_ring->br) != NULL &&
 	    (if_getdrvflags(ifp) & IFF_RUNNING) != 0) {
 		ENA_RING_MTX_LOCK(tx_ring);
+		if (tx_ring->stopping) {
+			ENA_RING_MTX_UNLOCK(tx_ring);
+			return;
+		}
 		ena_start_xmit(tx_ring);
 		ENA_RING_MTX_UNLOCK(tx_ring);
 	}
@@ -2954,7 +3059,8 @@ ena_mq_start(struct ifnet *ifp, struct m
 {
 	struct ena_adapter *adapter = ifp->if_softc;
 	struct ena_ring *tx_ring;
-	int ret, is_drbr_empty;
+	struct mbuf *is_drbr_empty;
+	bool ret;
 	uint32_t i;
 
 	if (unlikely((if_getdrvflags(adapter->ifp) & IFF_RUNNING) == 0))
@@ -2987,17 +3093,20 @@ ena_mq_start(struct ifnet *ifp, struct m
 	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)) {
+	is_drbr_empty = pcq_peek(tx_ring->br);
+	ret = pcq_put(tx_ring->br, m);
+	if (unlikely(ret == false)) {
+		m_freem(m);
+		counter_u64_add(tx_ring->tx_stats.pcq_drops, 1);
 		if (atomic_cas_uint(&tx_ring->task_pending, 0, 1) == 0)
 			workqueue_enqueue(tx_ring->enqueue_tq, &tx_ring->enqueue_task,
 			    curcpu());
-		return (ret);
+		return (ENOBUFS);
 	}
 
-	if ((is_drbr_empty != 0) && (ENA_RING_MTX_TRYLOCK(tx_ring) != 0)) {
-		ena_start_xmit(tx_ring);
+	if ((is_drbr_empty != NULL) && (ENA_RING_MTX_TRYLOCK(tx_ring) != 0)) {
+		if (!tx_ring->stopping)
+			ena_start_xmit(tx_ring);
 		ENA_RING_MTX_UNLOCK(tx_ring);
 	} else {
 		if (atomic_cas_uint(&tx_ring->task_pending, 0, 1) == 0)
@@ -3342,13 +3451,16 @@ static void ena_keep_alive_wd(void *adap
 {
 	struct ena_adapter *adapter = (struct ena_adapter *)adapter_data;
 	struct ena_admin_aenq_keep_alive_desc *desc;
-	uint64_t rx_drops;
+	uint64_t rx_drops, old;
 
 	desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e;
 
 	rx_drops = ((uint64_t)desc->rx_drops_high << 32) | desc->rx_drops_low;
-	counter_u64_zero(adapter->hw_stats.rx_drops);
-	counter_u64_add(adapter->hw_stats.rx_drops, rx_drops);
+	old = adapter->hw_stats.rx_drops.ev_count;
+	if (rx_drops > old) {
+		counter_u64_add(adapter->hw_stats.rx_drops, rx_drops - old);
+		if_statadd(adapter->ifp, if_iqdrops, rx_drops - old);
+	}
 
 	atomic_store_release(&adapter->keep_alive_timestamp, getsbinuptime());
 }
@@ -3372,7 +3484,7 @@ static void check_for_missing_keep_alive
 		    "Keep alive watchdog timeout.\n");
 		counter_u64_add(adapter->dev_stats.wd_expired, 1);
 		adapter->reset_reason = ENA_REGS_RESET_KEEP_ALIVE_TO;
-		adapter->trigger_reset = true;
+		ENA_FLAG_SET_ATOMIC(ENA_FLAG_TRIGGER_RESET, adapter);
 	}
 }
 
@@ -3385,7 +3497,7 @@ static void check_for_admin_com_state(st
 		    "ENA admin queue is not in running state!\n");
 		counter_u64_add(adapter->dev_stats.admin_q_pause, 1);
 		adapter->reset_reason = ENA_REGS_RESET_ADMIN_TO;
-		adapter->trigger_reset = true;
+		ENA_FLAG_SET_ATOMIC(ENA_FLAG_TRIGGER_RESET, adapter);
 	}
 }
 
@@ -3430,7 +3542,8 @@ check_missing_comp_in_queue(struct ena_a
 				    missed_tx, adapter->missing_tx_threshold);
 				adapter->reset_reason =
 				    ENA_REGS_RESET_MISS_TX_CMPL;
-				adapter->trigger_reset = true;
+				ENA_FLAG_SET_ATOMIC(ENA_FLAG_TRIGGER_RESET,
+				    adapter);
 				return (EIO);
 			}
 		}
@@ -3454,10 +3567,10 @@ check_for_missing_tx_completions(struct 
 	/* Make sure the driver doesn't turn the device in other process */
 	rmb();
 
-	if (!adapter->up)
+	if (!ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter))
 		return;
 
-	if (adapter->trigger_reset)
+	if (ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter))
 		return;
 
 	if (adapter->missing_tx_timeout == 0)
@@ -3500,10 +3613,10 @@ check_for_empty_rx_ring(struct ena_adapt
 	struct ena_ring *rx_ring;
 	int i, refill_required;
 
-	if (!adapter->up)
+	if (!ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter))
 		return;
 
-	if (adapter->trigger_reset)
+	if (ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter))
 		return;
 
 	for (i = 0; i < adapter->num_queues; i++) {
@@ -3520,9 +3633,15 @@ check_for_empty_rx_ring(struct ena_adapt
 				device_printf(adapter->pdev,
 				    "trigger refill for ring %d\n", i);
 
+				ENA_RING_MTX_LOCK(rx_ring);
+				if (rx_ring->stopping) {
+					ENA_RING_MTX_UNLOCK(rx_ring);
+					return;
+				}
 				if (atomic_cas_uint(&rx_ring->task_pending, 0, 1) == 0)
-					workqueue_enqueue(rx_ring->cmpl_tq,
-					    &rx_ring->cmpl_task, curcpu());
+					workqueue_enqueue(rx_ring->cleanup_tq,
+					    &rx_ring->cleanup_task, curcpu());
+				ENA_RING_MTX_UNLOCK(rx_ring);
 				rx_ring->empty_rx_queue = 0;
 			}
 		} else {
@@ -3549,7 +3668,7 @@ ena_timer_service(void *data)
 	if (host_info != NULL)
 		ena_update_host_info(host_info, adapter->ifp);
 
-	if (unlikely(adapter->trigger_reset)) {
+	if (unlikely(ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter))) {
 		device_printf(adapter->pdev, "Trigger reset is on\n");
 		workqueue_enqueue(adapter->reset_tq, &adapter->reset_task,
 		    curcpu());
@@ -3559,7 +3678,8 @@ ena_timer_service(void *data)
 	/*
 	 * Schedule another timeout one second from now.
 	 */
-	callout_schedule(&adapter->timer_service, hz);
+	if (likely(ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter)))
+		callout_schedule(&adapter->timer_service, hz);
 }
 
 static void
@@ -3571,17 +3691,17 @@ ena_reset_task(struct work *wk, void *ar
 	bool dev_up;
 	int rc;
 
-	if (unlikely(!adapter->trigger_reset)) {
+	if (unlikely(!ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter))) {
 		device_printf(adapter->pdev,
 		    "device reset scheduled but trigger_reset is off\n");
 		return;
 	}
 
-	rw_enter(&adapter->ioctl_sx, RW_WRITER);
+	ENA_CORE_MTX_LOCK(adapter);
 
-	callout_halt(&adapter->timer_service, &adapter->global_mtx);
+	callout_halt(&adapter->timer_service, NULL);
 
-	dev_up = adapter->up;
+	dev_up = ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter);
 
 	ena_com_set_admin_running_state(ena_dev, false);
 	ena_down(adapter);
@@ -3593,7 +3713,7 @@ ena_reset_task(struct work *wk, void *ar
 	ena_com_mmio_reg_read_request_destroy(ena_dev);
 
 	adapter->reset_reason = ENA_REGS_RESET_NORMAL;
-	adapter->trigger_reset = false;
+	ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_TRIGGER_RESET, adapter);
 
 	/* Finished destroy part. Restart the device */
 	rc = ena_device_init(adapter, adapter->pdev, &get_feat_ctx,
@@ -3622,9 +3742,7 @@ ena_reset_task(struct work *wk, void *ar
 		}
 	}
 
-	callout_schedule(&adapter->timer_service, hz);
-
-	rw_exit(&adapter->ioctl_sx);
+	ENA_CORE_MTX_UNLOCK(adapter);
 
 	return;
 
@@ -3635,8 +3753,8 @@ err_com_free:
 	ena_com_admin_destroy(ena_dev);
 err_dev_free:
 	device_printf(adapter->pdev, "ENA reset failed!\n");
-	adapter->running = false;
-	rw_exit(&adapter->ioctl_sx);
+	ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_DEVICE_RUNNING, adapter);
+	ENA_CORE_MTX_UNLOCK(adapter);
 }
 
 /**
@@ -3681,8 +3799,7 @@ ena_attach(device_t parent, device_t sel
         	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
 	}
 
-	mutex_init(&adapter->global_mtx, MUTEX_DEFAULT, IPL_NET);
-	rw_init(&adapter->ioctl_sx);
+	mutex_init(&adapter->global_mtx, MUTEX_DEFAULT, IPL_SOFTNET);
 
 	/* Set up the timer service */
 	adapter->keep_alive_timeout = DEFAULT_KEEP_ALIVE_TO;
@@ -3728,7 +3845,7 @@ ena_attach(device_t parent, device_t sel
 	adapter->tx_offload_cap = get_feat_ctx.offload.tx;
 
 	/* Set for sure that interface is not up */
-	adapter->up = false;
+	ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_DEV_UP, adapter);
 
 	memcpy(adapter->mac_addr, get_feat_ctx.dev_attr.mac_addr,
 	    ETHER_ADDR_LEN);
@@ -3804,21 +3921,21 @@ ena_attach(device_t parent, device_t sel
 	}
 
 	/* Initialize statistics */
-	ena_alloc_counters_dev(&adapter->dev_stats, io_queue_num);
-	ena_alloc_counters_hwstats(&adapter->hw_stats, io_queue_num);
+	ena_alloc_counters_dev(adapter, &adapter->dev_stats, io_queue_num);
+	ena_alloc_counters_hwstats(adapter, &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_OACTIVE, IFF_RUNNING);
+	ena_set_stopping_flag(adapter, false);
 
-	adapter->running = true;
+	ENA_FLAG_SET_ATOMIC(ENA_FLAG_DEVICE_RUNNING, adapter);
 	return;
 
 err_ifp_free:
 	if_detach(adapter->ifp);
-	if_free(adapter->ifp);
 err_io_free:
 	ena_free_all_io_rings_resources(adapter);
 #if 0
@@ -3858,20 +3975,20 @@ ena_detach(device_t pdev, int flags)
 		return (EBUSY);
 	}
 
+	ENA_CORE_MTX_LOCK(adapter);
+	ena_down(adapter);
+	ENA_CORE_MTX_UNLOCK(adapter);
+
 	/* Free reset task and callout */
-	callout_halt(&adapter->timer_service, &adapter->global_mtx);
+	callout_halt(&adapter->timer_service, NULL);
 	callout_destroy(&adapter->timer_service);
 	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);
-	rw_exit(&adapter->ioctl_sx);
-
 	if (adapter->ifp != NULL) {
 		ether_ifdetach(adapter->ifp);
-		if_free(adapter->ifp);
+		if_detach(adapter->ifp);
 	}
 	ifmedia_fini(&adapter->media);
 
@@ -3900,7 +4017,7 @@ ena_detach(device_t pdev, int flags)
 #endif
 
 	/* Reset the device only if the device is running. */
-	if (adapter->running)
+	if (ENA_FLAG_ISSET(ENA_FLAG_DEVICE_RUNNING, adapter))
 		ena_com_dev_reset(ena_dev, adapter->reset_reason);
 
 	ena_com_delete_host_info(ena_dev);
@@ -3918,7 +4035,6 @@ ena_detach(device_t pdev, int flags)
 	ena_free_pci_resources(adapter);
 
 	mutex_destroy(&adapter->global_mtx);
-	rw_destroy(&adapter->ioctl_sx);
 
 	if (ena_dev->bus != NULL)
 		free(ena_dev->bus, M_DEVBUF);
@@ -3952,16 +4068,13 @@ ena_update_on_link_change(void *adapter_
 
 	if (status != 0) {
 		device_printf(adapter->pdev, "link is UP\n");
+		ENA_FLAG_SET_ATOMIC(ENA_FLAG_LINK_UP, adapter);
 		if_link_state_change(ifp, LINK_STATE_UP);
-	} else if (status == 0) {
+	} else {
 		device_printf(adapter->pdev, "link is DOWN\n");
+		ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_LINK_UP, adapter);
 		if_link_state_change(ifp, LINK_STATE_DOWN);
-	} else {
-		device_printf(adapter->pdev, "invalid value recvd\n");
-		BUG();
 	}
-
-	adapter->link_status = status;
 }
 
 /**

Index: src/sys/dev/pci/if_enavar.h
diff -u src/sys/dev/pci/if_enavar.h:1.7 src/sys/dev/pci/if_enavar.h:1.8
--- src/sys/dev/pci/if_enavar.h:1.7	Sun Dec 23 12:32:33 2018
+++ src/sys/dev/pci/if_enavar.h	Mon Jul 19 21:16:33 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_enavar.h,v 1.7 2018/12/23 12:32:33 jmcneill Exp $	*/
+/*	$NetBSD: if_enavar.h,v 1.8 2021/07/19 21:16:33 jmcneill Exp $	*/
 
 /*-
  * BSD LICENSE
@@ -37,6 +37,8 @@
 #define ENA_H
 
 #include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/pcq.h>
 
 #include "external/bsd/ena-com/ena_com.h"
 #include "external/bsd/ena-com/ena_eth_com.h"
@@ -147,6 +149,29 @@
 #define	PCI_DEV_ID_ENA_VF	0xec20
 #define	PCI_DEV_ID_ENA_LLQ_VF	0xec21
 
+/*
+ * Flags indicating current ENA driver state
+ */
+enum ena_flags_t {
+	ENA_FLAG_DEVICE_RUNNING,
+	ENA_FLAG_DEV_UP,
+	ENA_FLAG_LINK_UP,
+	ENA_FLAG_MSIX_ENABLED,
+	ENA_FLAG_TRIGGER_RESET,
+	ENA_FLAG_ONGOING_RESET,
+	ENA_FLAG_DEV_UP_BEFORE_RESET,
+	ENA_FLAG_RSS_ACTIVE,
+	ENA_FLAGS_NUMBER = ENA_FLAG_RSS_ACTIVE
+};
+
+#define ENA_FLAG_BITMASK(bit)	(~(uint32_t)__BIT(bit))
+#define ENA_FLAG_ZERO(adapter)	(adapter)->flags = 0;
+#define ENA_FLAG_ISSET(bit, adapter)	((adapter)->flags & __BIT(bit))
+#define ENA_FLAG_SET_ATOMIC(bit, adapter)	\
+	atomic_or_32(&(adapter)->flags, __BIT(bit))
+#define ENA_FLAG_CLEAR_ATOMIC(bit, adapter)	\
+	atomic_and_32(&(adapter)->flags, ENA_FLAG_BITMASK(bit))
+
 typedef __int64_t sbintime_t;
 
 struct msix_entry {
@@ -201,6 +226,7 @@ struct ena_stats_tx {
 	struct evcnt bad_req_id;
 	struct evcnt collapse;
 	struct evcnt collapse_err;
+	struct evcnt pcq_drops;
 };
 
 struct ena_stats_rx {
@@ -209,7 +235,6 @@ struct ena_stats_rx {
 	struct evcnt bytes;
 	struct evcnt refil_partial;
 	struct evcnt bad_csum;
-	struct evcnt mjum_alloc_fail;
 	struct evcnt mbuf_alloc_fail;
 	struct evcnt dma_mapping_err;
 	struct evcnt bad_desc_num;
@@ -217,6 +242,22 @@ struct ena_stats_rx {
 	struct evcnt empty_rx_ring;
 };
 
+/*
+ * Locking notes:
+ * + For TX, a field in ena_ring is protected by ring_mtx (a spin mutex).
+ *   - protect them only when I/F is up.
+ *   - when I/F is down or attaching, detaching, no need to protect them.
+ * + For RX, a field "stopping" is protected by ring_mtx (a spin mutex).
+ *   - other fields in ena_ring are not protected.
+ * + a fields in ena_adapter is protected by global_mtx (a adaptive mutex).
+ *
+ * + a field marked "stable" is unlocked.
+ * + a field marked "atomic" is unlocked,
+ *   but must use atomic ops to read/write.
+ *
+ * Lock order:
+ * + global_mtx -> ring_mtx
+ */
 struct ena_ring {
 	/* Holds the empty requests for TX/RX out of order completions */
 	union {
@@ -258,7 +299,7 @@ struct ena_ring {
 	};
 	int ring_size; /* number of tx/rx_buffer_info's entries */
 
-	struct buf_ring *br; /* only for TX */
+	pcq_t *br; /* only for TX */
 
 	kmutex_t ring_mtx;
 	char mtx_name[16];
@@ -269,11 +310,12 @@ struct ena_ring {
 			struct workqueue *enqueue_tq;
 		};
 		struct {
-			struct work cmpl_task;
-			struct workqueue *cmpl_tq;
+			struct work cleanup_task;
+			struct workqueue *cleanup_tq;
 		};
 	};
-	u_int task_pending;
+	u_int task_pending; /* atomic */
+	bool stopping;
 
 	union {
 		struct ena_stats_tx tx_stats;
@@ -314,7 +356,6 @@ struct ena_adapter {
 
 	/* OS resources */
 	kmutex_t global_mtx;
-	krwlock_t ioctl_sx;
 
 	void *sc_ihs[ENA_MAX_MSIX_VEC(ENA_MAX_NUM_IO_QUEUES)];
 	pci_intr_handle_t *sc_intrs;
@@ -324,6 +365,8 @@ struct ena_adapter {
 	/* Registers */
 	bus_space_handle_t sc_bhandle;
 	bus_space_tag_t	sc_btag;
+	bus_addr_t sc_memaddr;
+	bus_size_t sc_mapsize;
 
 	/* DMA tag used throughout the driver adapter for Tx and Rx */
 	bus_dma_tag_t sc_dmat;
@@ -349,14 +392,11 @@ struct ena_adapter {
 	uint8_t mac_addr[ETHER_ADDR_LEN];
 	/* mdio and phy*/
 
-	bool link_status;
-	bool trigger_reset;
-	bool up;
-	bool running;
+	uint32_t flags; /* atomic */
 
 	/* Queue will represent one TX and one RX ring */
 	struct ena_que que[ENA_MAX_NUM_IO_QUEUES]
-	    __aligned(CACHE_LINE_SIZE);
+	    __aligned(CACHE_LINE_SIZE); /* stable */
 
 	/* TX */
 	struct ena_ring tx_ring[ENA_MAX_NUM_IO_QUEUES]
@@ -388,6 +428,12 @@ struct ena_adapter {
 #define	ENA_RING_MTX_LOCK(_ring)	mutex_enter(&(_ring)->ring_mtx)
 #define	ENA_RING_MTX_TRYLOCK(_ring)	mutex_tryenter(&(_ring)->ring_mtx)
 #define	ENA_RING_MTX_UNLOCK(_ring)	mutex_exit(&(_ring)->ring_mtx)
+#define	ENA_RING_MTX_OWNED(_ring)	mutex_owned(&(_ring)->ring_mtx)
+
+#define	ENA_CORE_MTX_LOCK(_adapter)		mutex_enter(&(_adapter)->global_mtx)
+#define	ENA_CORE_MTX_TRYLOCK(_adapter)	mutex_tryenter(&(_adapter)->global_mtx)
+#define	ENA_CORE_MTX_UNLOCK(_adapter)	mutex_exit(&(_adapter)->global_mtx)
+#define	ENA_CORE_MTX_OWNED(_adapter)	mutex_owned(&(_adapter)->global_mtx)
 
 static inline int ena_mbuf_count(struct mbuf *mbuf)
 {

Index: src/sys/external/bsd/ena-com/ena_plat.h
diff -u src/sys/external/bsd/ena-com/ena_plat.h:1.6 src/sys/external/bsd/ena-com/ena_plat.h:1.7
--- src/sys/external/bsd/ena-com/ena_plat.h:1.6	Thu Apr 16 23:29:53 2020
+++ src/sys/external/bsd/ena-com/ena_plat.h	Mon Jul 19 21:16:33 2021
@@ -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.6 2020/04/16 23:29:53 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ena_plat.h,v 1.7 2021/07/19 21:16:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -312,9 +312,11 @@ int	ena_dma_alloc(device_t dmadev, bus_s
 #define ENA_MEM_FREE_COHERENT(dmadev, size, virt, phys, dma)		\
 	do {								\
 		(void)size;						\
+		size_t mapsize = (dma).map->dm_mapsize;			\
 		bus_dmamap_unload((dma).tag, (dma).map);		\
+		bus_dmamem_unmap((dma).tag, (dma).vaddr, mapsize);	\
 		bus_dmamem_free((dma).tag, &(dma).seg, (dma).nseg);	\
-		bus_dma_tag_destroy((dma).tag);	/* XXX remove */	\
+		bus_dmamap_destroy((dma).tag, (dma).map);		\
 		(dma).tag = NULL;					\
 		(virt) = NULL;						\
 	} while (0)

Reply via email to