On 18/02/20(Tue) 22:39, Jonathan Matthew wrote:
> On Fri, Feb 14, 2020 at 06:28:20PM +0100, Martin Pieuchot wrote:
> > @@ -2597,13 +2635,6 @@ em_initialize_receive_unit(struct em_sof
> >             E1000_WRITE_REG(&sc->hw, ITR, DEFAULT_ITR);
> >     }
> >  
> > -   /* Setup the Base and Length of the Rx Descriptor Ring */
> > -   bus_addr = sc->sc_rx_dma.dma_map->dm_segs[0].ds_addr;
> > -   E1000_WRITE_REG(&sc->hw, RDLEN(0),
> > -       sc->sc_rx_slots * sizeof(*sc->sc_rx_desc_ring));
> > -   E1000_WRITE_REG(&sc->hw, RDBAH(0), (u_int32_t)(bus_addr >> 32));
> > -   E1000_WRITE_REG(&sc->hw, RDBAL(0), (u_int32_t)bus_addr);
> > -
> >     /* Setup the Receive Control Register */
> >     reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
> >         E1000_RCTL_RDMTS_HALF |
> > @@ -2653,6 +2684,13 @@ em_initialize_receive_unit(struct em_sof
> >     if (sc->hw.mac_type == em_82573)
> >             E1000_WRITE_REG(&sc->hw, RDTR, 0x20);
> >  
> > +   /* Setup the Base and Length of the Rx Descriptor Ring */
> > +   bus_addr = que->rx.sc_rx_dma.dma_map->dm_segs[0].ds_addr;
> > +   E1000_WRITE_REG(&sc->hw, RDLEN(0),
> > +       sc->sc_rx_slots * sizeof(*que->rx.sc_rx_desc_ring));
> > +   E1000_WRITE_REG(&sc->hw, RDBAH(0), (u_int32_t)(bus_addr >> 32));
> > +   E1000_WRITE_REG(&sc->hw, RDBAL(0), (u_int32_t)bus_addr);
> > +
> 
> Just to make sure that I follow how this works, should we be setting
> RDLEN(que->me) rather than RDLEN(0) here, and likewise for RDBAH and RDBAL?
> This value is always 0 at this stage, so of course it doesn't matter yet.

Nice catch!  Diff below fixes these :o)

Index: dev/pci/if_em.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em.c,v
retrieving revision 1.344
diff -u -p -r1.344 if_em.c
--- dev/pci/if_em.c     4 Feb 2020 10:59:23 -0000       1.344
+++ dev/pci/if_em.c     18 Feb 2020 13:04:19 -0000
@@ -257,25 +257,25 @@ void em_free_transmit_structures(struct 
 void em_free_receive_structures(struct em_softc *);
 void em_update_stats_counters(struct em_softc *);
 void em_disable_aspm(struct em_softc *);
-void em_txeof(struct em_softc *);
+void em_txeof(struct em_queue *);
 int  em_allocate_receive_structures(struct em_softc *);
 int  em_allocate_transmit_structures(struct em_softc *);
 int  em_allocate_desc_rings(struct em_softc *);
-int  em_rxfill(struct em_softc *);
+int  em_rxfill(struct em_queue *);
 void em_rxrefill(void *);
-int  em_rxeof(struct em_softc *);
+int  em_rxeof(struct em_queue *);
 void em_receive_checksum(struct em_softc *, struct em_rx_desc *,
                         struct mbuf *);
-u_int  em_transmit_checksum_setup(struct em_softc *, struct mbuf *, u_int,
+u_int  em_transmit_checksum_setup(struct em_queue *, struct mbuf *, u_int,
            u_int32_t *, u_int32_t *);
 void em_iff(struct em_softc *);
 #ifdef EM_DEBUG
 void em_print_hw_stats(struct em_softc *);
 #endif
 void em_update_link_status(struct em_softc *);
-int  em_get_buf(struct em_softc *, int);
+int  em_get_buf(struct em_queue *, int);
 void em_enable_hw_vlans(struct em_softc *);
-u_int em_encap(struct em_softc *, struct mbuf *);
+u_int em_encap(struct em_queue *, struct mbuf *);
 void em_smartspeed(struct em_softc *);
 int  em_82547_fifo_workaround(struct em_softc *, int);
 void em_82547_update_fifo_head(struct em_softc *, int);
@@ -286,8 +286,8 @@ int  em_dma_malloc(struct em_softc *, bu
 void em_dma_free(struct em_softc *, struct em_dma_alloc *);
 u_int32_t em_fill_descriptors(u_int64_t address, u_int32_t length,
                              PDESC_ARRAY desc_array);
-void em_flush_tx_ring(struct em_softc *);
-void em_flush_rx_ring(struct em_softc *);
+void em_flush_tx_ring(struct em_queue *);
+void em_flush_rx_ring(struct em_queue *);
 void em_flush_desc_rings(struct em_softc *);
 
 /*********************************************************************
@@ -383,7 +383,6 @@ em_attach(struct device *parent, struct 
 
        timeout_set(&sc->timer_handle, em_local_timer, sc);
        timeout_set(&sc->tx_fifo_timer_handle, em_82547_move_tail, sc);
-       timeout_set(&sc->rx_refill, em_rxrefill, sc);
 
        /* Determine hardware revision */
        em_identify_hardware(sc);
@@ -601,6 +600,7 @@ em_start(struct ifqueue *ifq)
        u_int head, free, used;
        struct mbuf *m;
        int post = 0;
+       struct em_queue *que = sc->queues; /* Use only first queue. */
 
        if (!sc->link_active) {
                ifq_purge(ifq);
@@ -608,15 +608,15 @@ em_start(struct ifqueue *ifq)
        }
 
        /* calculate free space */
-       head = sc->sc_tx_desc_head;
-       free = sc->sc_tx_desc_tail;
+       head = que->tx.sc_tx_desc_head;
+       free = que->tx.sc_tx_desc_tail;
        if (free <= head)
                free += sc->sc_tx_slots;
        free -= head;
 
        if (sc->hw.mac_type != em_82547) {
-               bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-                   0, sc->sc_tx_dma.dma_map->dm_mapsize,
+               bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+                   0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        }
 
@@ -631,7 +631,7 @@ em_start(struct ifqueue *ifq)
                if (m == NULL)
                        break;
 
-               used = em_encap(sc, m);
+               used = em_encap(que, m);
                if (used == 0) {
                        m_freem(m);
                        continue;
@@ -656,8 +656,8 @@ em_start(struct ifqueue *ifq)
                        if (sc->link_duplex == HALF_DUPLEX)
                                em_82547_move_tail_locked(sc);
                        else {
-                               E1000_WRITE_REG(&sc->hw, TDT(0),
-                                   sc->sc_tx_desc_head);
+                               E1000_WRITE_REG(&sc->hw, TDT(que->me),
+                                   que->tx.sc_tx_desc_head);
                                em_82547_update_fifo_head(sc, len);
                        }
                }
@@ -666,8 +666,8 @@ em_start(struct ifqueue *ifq)
        }
 
        if (sc->hw.mac_type != em_82547) {
-               bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-                   0, sc->sc_tx_dma.dma_map->dm_mapsize,
+               bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+                   0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                /* 
                 * Advance the Transmit Descriptor Tail (Tdt),
@@ -675,7 +675,8 @@ em_start(struct ifqueue *ifq)
                 * available to transmit.
                 */
                if (post)
-                       E1000_WRITE_REG(&sc->hw, TDT(0), sc->sc_tx_desc_head);
+                       E1000_WRITE_REG(&sc->hw, TDT(que->me),
+                           que->tx.sc_tx_desc_head);
        }
 }
 
@@ -735,7 +736,7 @@ em_ioctl(struct ifnet *ifp, u_long comma
 
        case SIOCGIFRXR:
                error = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data,
-                   NULL, EM_MCLBYTES, &sc->sc_rx_ring);
+                   NULL, EM_MCLBYTES, &sc->queues->rx.sc_rx_ring);
                break;
 
        default:
@@ -768,6 +769,8 @@ void
 em_watchdog(struct ifnet *ifp)
 {
        struct em_softc *sc = ifp->if_softc;
+       struct em_queue *que = sc->queues; /* Use only first queue. */
+
 
        /* If we are in this routine because of pause frames, then
         * don't reset the hardware.
@@ -778,8 +781,9 @@ em_watchdog(struct ifnet *ifp)
        }
        printf("%s: watchdog: head %u tail %u TDH %u TDT %u\n",
            DEVNAME(sc),
-           sc->sc_tx_desc_head, sc->sc_tx_desc_tail,
-           E1000_READ_REG(&sc->hw, TDH(0)), E1000_READ_REG(&sc->hw, TDT(0)));
+           que->tx.sc_tx_desc_head, que->tx.sc_tx_desc_tail,
+           E1000_READ_REG(&sc->hw, TDH(que->me)),
+           E1000_READ_REG(&sc->hw, TDT(que->me)));
 
        em_init(sc);
 
@@ -940,6 +944,7 @@ int 
 em_intr(void *arg)
 {
        struct em_softc *sc = arg;
+       struct em_queue *que = sc->queues; /* single queue */
        struct ifnet    *ifp = &sc->sc_ac.ac_if;
        u_int32_t       reg_icr, test_icr;
 
@@ -950,9 +955,9 @@ em_intr(void *arg)
                return (0);
 
        if (ifp->if_flags & IFF_RUNNING) {
-               em_txeof(sc);
-               if (em_rxeof(sc))
-                       em_rxrefill(sc);
+               em_txeof(que);
+               if (em_rxeof(que))
+                       em_rxrefill(que);
        }
 
        /* Link status change */
@@ -1120,8 +1125,9 @@ em_flowstatus(struct em_softc *sc)
  *  return 0 on success, positive on failure
  **********************************************************************/
 u_int
-em_encap(struct em_softc *sc, struct mbuf *m)
+em_encap(struct em_queue *que, struct mbuf *m)
 {
+       struct em_softc *sc = que->sc;
        struct em_packet *pkt;
        struct em_tx_desc *desc;
        bus_dmamap_t map;
@@ -1134,8 +1140,8 @@ em_encap(struct em_softc *sc, struct mbu
        u_int32_t               array_elements;
 
        /* get a dmamap for this packet from the next free slot */
-       head = sc->sc_tx_desc_head;
-       pkt = &sc->sc_tx_pkts_ring[head];
+       head = que->tx.sc_tx_desc_head;
+       pkt = &que->tx.sc_tx_pkts_ring[head];
        map = pkt->pkt_map;
 
        switch (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT)) {
@@ -1158,8 +1164,8 @@ em_encap(struct em_softc *sc, struct mbu
            BUS_DMASYNC_PREWRITE);
 
        if (sc->hw.mac_type == em_82547) {
-               bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-                   0, sc->sc_tx_dma.dma_map->dm_mapsize,
+               bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+                   0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        }
 
@@ -1167,7 +1173,7 @@ em_encap(struct em_softc *sc, struct mbu
            sc->hw.mac_type != em_82576 &&
            sc->hw.mac_type != em_82580 && sc->hw.mac_type != em_i210 &&
            sc->hw.mac_type != em_i350) {
-               used += em_transmit_checksum_setup(sc, m, head,
+               used += em_transmit_checksum_setup(que, m, head,
                    &txd_upper, &txd_lower);
        } else {
                txd_upper = txd_lower = 0;
@@ -1188,12 +1194,12 @@ em_encap(struct em_softc *sc, struct mbu
                            map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len,
                            &desc_array);
                        for (j = 0; j < array_elements; j++) {
-                               desc = &sc->sc_tx_desc_ring[head];
+                               desc = &que->tx.sc_tx_desc_ring[head];
 
                                desc->buffer_addr = htole64(
                                        desc_array.descriptor[j].address);
                                desc->lower.data = htole32(
-                                       (sc->sc_txd_cmd | txd_lower |
+                                       (que->tx.sc_txd_cmd | txd_lower |
                                         
(u_int16_t)desc_array.descriptor[j].length));
                                desc->upper.data = htole32(txd_upper);
 
@@ -1204,10 +1210,10 @@ em_encap(struct em_softc *sc, struct mbu
                                used++;
                        }
                } else {
-                       desc = &sc->sc_tx_desc_ring[head];
+                       desc = &que->tx.sc_tx_desc_ring[head];
 
                        desc->buffer_addr = htole64(map->dm_segs[i].ds_addr);
-                       desc->lower.data = htole32(sc->sc_txd_cmd |
+                       desc->lower.data = htole32(que->tx.sc_txd_cmd |
                            txd_lower | map->dm_segs[i].ds_len);
                        desc->upper.data = htole32(txd_upper);
 
@@ -1234,7 +1240,7 @@ em_encap(struct em_softc *sc, struct mbu
        pkt->pkt_m = m;
        pkt->pkt_eop = last;
 
-       sc->sc_tx_desc_head = head;
+       que->tx.sc_tx_desc_head = head;
 
        /* 
         * Last Descriptor of Packet
@@ -1244,8 +1250,8 @@ em_encap(struct em_softc *sc, struct mbu
        desc->lower.data |= htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS);
 
        if (sc->hw.mac_type == em_82547) {
-               bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-                   0, sc->sc_tx_dma.dma_map->dm_mapsize,
+               bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+                   0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        }
 
@@ -1268,12 +1274,13 @@ em_82547_move_tail_locked(struct em_soft
        struct em_tx_desc *tx_desc;
        uint16_t length = 0;
        boolean_t eop = 0;
+       struct em_queue *que = sc->queues; /* single queue chip */
 
-       hw_tdt = E1000_READ_REG(&sc->hw, TDT(0));
-       sw_tdt = sc->sc_tx_desc_head;
+       hw_tdt = E1000_READ_REG(&sc->hw, TDT(que->me));
+       sw_tdt = que->tx.sc_tx_desc_head;
 
        while (hw_tdt != sw_tdt) {
-               tx_desc = &sc->sc_tx_desc_ring[hw_tdt];
+               tx_desc = &que->tx.sc_tx_desc_ring[hw_tdt];
                length += tx_desc->lower.flags.length;
                eop = tx_desc->lower.data & E1000_TXD_CMD_EOP;
                if (++hw_tdt == sc->sc_tx_slots)
@@ -1285,7 +1292,7 @@ em_82547_move_tail_locked(struct em_soft
                                timeout_add(&sc->tx_fifo_timer_handle, 1);
                                break;
                        }
-                       E1000_WRITE_REG(&sc->hw, TDT(0), hw_tdt);
+                       E1000_WRITE_REG(&sc->hw, TDT(que->me), hw_tdt);
                        em_82547_update_fifo_head(sc, length);
                        length = 0;
                }
@@ -1339,9 +1346,10 @@ int
 em_82547_tx_fifo_reset(struct em_softc *sc)
 {
        uint32_t tctl;
+       struct em_queue *que = sc->queues; /* single queue chip */
 
-       if ((E1000_READ_REG(&sc->hw, TDT(0)) ==
-            E1000_READ_REG(&sc->hw, TDH(0))) &&
+       if ((E1000_READ_REG(&sc->hw, TDT(que->me)) ==
+            E1000_READ_REG(&sc->hw, TDH(que->me))) &&
            (E1000_READ_REG(&sc->hw, TDFT) ==
             E1000_READ_REG(&sc->hw, TDFH)) &&
            (E1000_READ_REG(&sc->hw, TDFTS) ==
@@ -1516,6 +1524,7 @@ void
 em_stop(void *arg, int softonly)
 {
        struct em_softc *sc = arg;
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct ifnet   *ifp = &sc->sc_ac.ac_if;
 
        /* Tell the stack that the interface is no longer active */
@@ -1523,7 +1532,7 @@ em_stop(void *arg, int softonly)
 
        INIT_DEBUGOUT("em_stop: begin");
 
-       timeout_del(&sc->rx_refill);
+       timeout_del(&que->rx_refill);
        timeout_del(&sc->timer_handle);
        timeout_del(&sc->tx_fifo_timer_handle);
 
@@ -1615,6 +1624,7 @@ em_allocate_pci_resources(struct em_soft
        const char              *intrstr = NULL;
        struct pci_attach_args *pa = &sc->osdep.em_pa;
        pci_chipset_tag_t       pc = pa->pa_pc;
+       struct em_queue        *que = NULL;
 
        val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_MMBA);
        if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) {
@@ -1684,6 +1694,18 @@ em_allocate_pci_resources(struct em_soft
                }
         }
 
+       /* Only one queue for the moment. */
+       que = malloc(sizeof(struct em_queue), M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (que == NULL) {
+               printf(": unable to allocate queue memory\n");
+               return (ENOMEM);
+       }
+       que->me = 0;
+       que->sc = sc;
+       timeout_set(&que->rx_refill, em_rxrefill, que);
+
+       sc->queues = que;
+       sc->num_queues = 1;
        sc->legacy_irq = 0;
        if (pci_intr_map_msi(pa, &ih)) {
                if (pci_intr_map(pa, &ih)) {
@@ -1736,7 +1758,7 @@ em_free_pci_resources(struct em_softc *s
 {
        struct pci_attach_args *pa = &sc->osdep.em_pa;
        pci_chipset_tag_t       pc = pa->pa_pc;
-
+       struct em_queue        *que = NULL;
        if (sc->sc_intrhand)
                pci_intr_disestablish(pc, sc->sc_intrhand);
        sc->sc_intrhand = 0;
@@ -1756,14 +1778,20 @@ em_free_pci_resources(struct em_softc *s
                                sc->osdep.em_memsize);
        sc->osdep.em_membase = 0;
 
-       if (sc->sc_rx_desc_ring != NULL) {
-               sc->sc_rx_desc_ring = NULL;
-               em_dma_free(sc, &sc->sc_rx_dma);
-       }
-       if (sc->sc_tx_desc_ring != NULL) {
-               sc->sc_tx_desc_ring = NULL;
-               em_dma_free(sc, &sc->sc_tx_dma);
-       }
+       que = sc->queues; /* Use only first queue. */
+       if (que->rx.sc_rx_desc_ring != NULL) {
+               que->rx.sc_rx_desc_ring = NULL;
+               em_dma_free(sc, &que->rx.sc_rx_dma);
+       }
+       if (que->tx.sc_tx_desc_ring != NULL) {
+               que->tx.sc_tx_desc_ring = NULL;
+               em_dma_free(sc, &que->tx.sc_tx_dma);
+       }
+       if (sc->queues)
+               free(sc->queues, M_DEVBUF,
+                   sc->num_queues * sizeof(struct em_queue));
+       sc->num_queues = 0;
+       sc->queues = NULL;
 }
 
 /*********************************************************************
@@ -2113,13 +2141,15 @@ em_dma_free(struct em_softc *sc, struct 
 int
 em_allocate_transmit_structures(struct em_softc *sc)
 {
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-           0, sc->sc_tx_dma.dma_map->dm_mapsize,
+       struct em_queue *que = sc->queues; /* Use only first queue. */
+
+       bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+           0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-       sc->sc_tx_pkts_ring = mallocarray(sc->sc_tx_slots,
-           sizeof(*sc->sc_tx_pkts_ring), M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (sc->sc_tx_pkts_ring == NULL) {
+       que->tx.sc_tx_pkts_ring = mallocarray(sc->sc_tx_slots,
+           sizeof(*que->tx.sc_tx_pkts_ring), M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (que->tx.sc_tx_pkts_ring == NULL) {
                printf("%s: Unable to allocate tx_buffer memory\n", 
                       DEVNAME(sc));
                return (ENOMEM);
@@ -2136,17 +2166,18 @@ em_allocate_transmit_structures(struct e
 int
 em_setup_transmit_structures(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct em_packet *pkt;
        int error, i;
 
        if ((error = em_allocate_transmit_structures(sc)) != 0)
                goto fail;
 
-       bzero((void *) sc->sc_tx_desc_ring,
+       bzero((void *) que->tx.sc_tx_desc_ring,
              (sizeof(struct em_tx_desc)) * sc->sc_tx_slots);
 
        for (i = 0; i < sc->sc_tx_slots; i++) {
-               pkt = &sc->sc_tx_pkts_ring[i];
+               pkt = &que->tx.sc_tx_pkts_ring[i];
                error = bus_dmamap_create(sc->sc_dmat, MAX_JUMBO_FRAME_SIZE,
                    EM_MAX_SCATTER / (sc->pcix_82544 ? 2 : 1),
                    MAX_JUMBO_FRAME_SIZE, 0, BUS_DMA_NOWAIT, &pkt->pkt_map);
@@ -2157,11 +2188,11 @@ em_setup_transmit_structures(struct em_s
                }
        }
 
-       sc->sc_tx_desc_head = 0;
-       sc->sc_tx_desc_tail = 0;
+       que->tx.sc_tx_desc_head = 0;
+       que->tx.sc_tx_desc_tail = 0;
 
        /* Set checksum context */
-       sc->active_checksum_context = OFFLOAD_NONE;
+       que->tx.active_checksum_context = OFFLOAD_NONE;
 
        return (0);
 
@@ -2178,26 +2209,27 @@ fail:
 void
 em_initialize_transmit_unit(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        u_int32_t       reg_tctl, reg_tipg = 0;
        u_int64_t       bus_addr;
 
        INIT_DEBUGOUT("em_initialize_transmit_unit: begin");
 
        /* Setup the Base and Length of the Tx Descriptor Ring */
-       bus_addr = sc->sc_tx_dma.dma_map->dm_segs[0].ds_addr;
-       E1000_WRITE_REG(&sc->hw, TDLEN(0),
+       bus_addr = que->tx.sc_tx_dma.dma_map->dm_segs[0].ds_addr;
+       E1000_WRITE_REG(&sc->hw, TDLEN(que->me),
                        sc->sc_tx_slots *
                        sizeof(struct em_tx_desc));
-       E1000_WRITE_REG(&sc->hw, TDBAH(0), (u_int32_t)(bus_addr >> 32));
-       E1000_WRITE_REG(&sc->hw, TDBAL(0), (u_int32_t)bus_addr);
+       E1000_WRITE_REG(&sc->hw, TDBAH(que->me), (u_int32_t)(bus_addr >> 32));
+       E1000_WRITE_REG(&sc->hw, TDBAL(que->me), (u_int32_t)bus_addr);
 
        /* Setup the HW Tx Head and Tail descriptor pointers */
-       E1000_WRITE_REG(&sc->hw, TDT(0), 0);
-       E1000_WRITE_REG(&sc->hw, TDH(0), 0);
+       E1000_WRITE_REG(&sc->hw, TDT(que->me), 0);
+       E1000_WRITE_REG(&sc->hw, TDH(que->me), 0);
 
        HW_DEBUGOUT2("Base = %x, Length = %x\n", 
-                    E1000_READ_REG(&sc->hw, TDBAL(0)),
-                    E1000_READ_REG(&sc->hw, TDLEN(0)));
+                    E1000_READ_REG(&sc->hw, TDBAL(que->me)),
+                    E1000_READ_REG(&sc->hw, TDLEN(que->me)));
 
        /* Set the default values for the Tx Inter Packet Gap timer */
        switch (sc->hw.mac_type) {
@@ -2228,17 +2260,17 @@ em_initialize_transmit_unit(struct em_so
                E1000_WRITE_REG(&sc->hw, TADV, sc->tx_abs_int_delay);
 
        /* Setup Transmit Descriptor Base Settings */   
-       sc->sc_txd_cmd = E1000_TXD_CMD_IFCS;
+       que->tx.sc_txd_cmd = E1000_TXD_CMD_IFCS;
 
        if (sc->hw.mac_type == em_82575 || sc->hw.mac_type == em_82580 ||
            sc->hw.mac_type == em_82576 ||
            sc->hw.mac_type == em_i210 || sc->hw.mac_type == em_i350) {
                /* 82575/6 need to enable the TX queue and lack the IDE bit */
-               reg_tctl = E1000_READ_REG(&sc->hw, TXDCTL(0));
+               reg_tctl = E1000_READ_REG(&sc->hw, TXDCTL(que->me));
                reg_tctl |= E1000_TXDCTL_QUEUE_ENABLE;
-               E1000_WRITE_REG(&sc->hw, TXDCTL(0), reg_tctl);
+               E1000_WRITE_REG(&sc->hw, TXDCTL(que->me), reg_tctl);
        } else if (sc->tx_int_delay > 0)
-               sc->sc_txd_cmd |= E1000_TXD_CMD_IDE;
+               que->tx.sc_txd_cmd |= E1000_TXD_CMD_IDE;
 
        /* Program the Transmit Control Register */
        reg_tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
@@ -2277,14 +2309,15 @@ em_initialize_transmit_unit(struct em_so
 void
 em_free_transmit_structures(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct em_packet *pkt;
        int i;
 
        INIT_DEBUGOUT("free_transmit_structures: begin");
 
-       if (sc->sc_tx_pkts_ring != NULL) {
+       if (que->tx.sc_tx_pkts_ring != NULL) {
                for (i = 0; i < sc->sc_tx_slots; i++) {
-                       pkt = &sc->sc_tx_pkts_ring[i];
+                       pkt = &que->tx.sc_tx_pkts_ring[i];
 
                        if (pkt->pkt_m != NULL) {
                                bus_dmamap_sync(sc->sc_dmat, pkt->pkt_map,
@@ -2302,13 +2335,13 @@ em_free_transmit_structures(struct em_so
                        }
                }
 
-               free(sc->sc_tx_pkts_ring, M_DEVBUF,
-                   sc->sc_tx_slots * sizeof(*sc->sc_tx_pkts_ring));
-               sc->sc_tx_pkts_ring = NULL;
+               free(que->tx.sc_tx_pkts_ring, M_DEVBUF,
+                   sc->sc_tx_slots * sizeof(*que->tx.sc_tx_pkts_ring));
+               que->tx.sc_tx_pkts_ring = NULL;
        }
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-           0, sc->sc_tx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+           0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 }
 
@@ -2320,7 +2353,7 @@ em_free_transmit_structures(struct em_so
  *
  **********************************************************************/
 u_int
-em_transmit_checksum_setup(struct em_softc *sc, struct mbuf *mp, u_int head,
+em_transmit_checksum_setup(struct em_queue *que, struct mbuf *mp, u_int head,
     u_int32_t *txd_upper, u_int32_t *txd_lower)
 {
        struct em_context_desc *TXD;
@@ -2328,17 +2361,17 @@ em_transmit_checksum_setup(struct em_sof
        if (mp->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
                *txd_upper = E1000_TXD_POPTS_TXSM << 8;
                *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
-               if (sc->active_checksum_context == OFFLOAD_TCP_IP)
+               if (que->tx.active_checksum_context == OFFLOAD_TCP_IP)
                        return (0);
                else
-                       sc->active_checksum_context = OFFLOAD_TCP_IP;
+                       que->tx.active_checksum_context = OFFLOAD_TCP_IP;
        } else if (mp->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
                *txd_upper = E1000_TXD_POPTS_TXSM << 8;
                *txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
-               if (sc->active_checksum_context == OFFLOAD_UDP_IP)
+               if (que->tx.active_checksum_context == OFFLOAD_UDP_IP)
                        return (0);
                else
-                       sc->active_checksum_context = OFFLOAD_UDP_IP;
+                       que->tx.active_checksum_context = OFFLOAD_UDP_IP;
        } else {
                *txd_upper = 0;
                *txd_lower = 0;
@@ -2348,7 +2381,7 @@ em_transmit_checksum_setup(struct em_sof
        /* If we reach this point, the checksum offload context
         * needs to be reset.
         */
-       TXD = (struct em_context_desc *)&sc->sc_tx_desc_ring[head];
+       TXD = (struct em_context_desc *)&que->tx.sc_tx_desc_ring[head];
 
        TXD->lower_setup.ip_fields.ipcss = ETHER_HDR_LEN;
        TXD->lower_setup.ip_fields.ipcso = 
@@ -2360,18 +2393,18 @@ em_transmit_checksum_setup(struct em_sof
            ETHER_HDR_LEN + sizeof(struct ip);
        TXD->upper_setup.tcp_fields.tucse = htole16(0);
 
-       if (sc->active_checksum_context == OFFLOAD_TCP_IP) {
+       if (que->tx.active_checksum_context == OFFLOAD_TCP_IP) {
                TXD->upper_setup.tcp_fields.tucso = 
                    ETHER_HDR_LEN + sizeof(struct ip) + 
                    offsetof(struct tcphdr, th_sum);
-       } else if (sc->active_checksum_context == OFFLOAD_UDP_IP) {
+       } else if (que->tx.active_checksum_context == OFFLOAD_UDP_IP) {
                TXD->upper_setup.tcp_fields.tucso = 
                    ETHER_HDR_LEN + sizeof(struct ip) + 
                    offsetof(struct udphdr, uh_sum);
        }
 
        TXD->tcp_seg_setup.data = htole32(0);
-       TXD->cmd_and_length = htole32(sc->sc_txd_cmd | E1000_TXD_CMD_DEXT);
+       TXD->cmd_and_length = htole32(que->tx.sc_txd_cmd | E1000_TXD_CMD_DEXT);
 
        return (1);
 }
@@ -2384,27 +2417,28 @@ em_transmit_checksum_setup(struct em_sof
  *
  **********************************************************************/
 void
-em_txeof(struct em_softc *sc)
+em_txeof(struct em_queue *que)
 {
+       struct em_softc *sc = que->sc;
        struct ifnet *ifp = &sc->sc_ac.ac_if;
        struct em_packet *pkt;
        struct em_tx_desc *desc;
        u_int head, tail;
        u_int free = 0;
 
-       head = sc->sc_tx_desc_head;
-       tail = sc->sc_tx_desc_tail;
+       head = que->tx.sc_tx_desc_head;
+       tail = que->tx.sc_tx_desc_tail;
 
        if (head == tail)
                return;
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-           0, sc->sc_tx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+           0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_POSTREAD);
 
        do {
-               pkt = &sc->sc_tx_pkts_ring[tail];
-               desc = &sc->sc_tx_desc_ring[pkt->pkt_eop];
+               pkt = &que->tx.sc_tx_pkts_ring[tail];
+               desc = &que->tx.sc_tx_desc_ring[pkt->pkt_eop];
 
                if (!ISSET(desc->upper.fields.status, E1000_TXD_STAT_DD))
                        break;
@@ -2427,14 +2461,14 @@ em_txeof(struct em_softc *sc)
                free++;
        } while (tail != head);
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_tx_dma.dma_map,
-           0, sc->sc_tx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->tx.sc_tx_dma.dma_map,
+           0, que->tx.sc_tx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_PREREAD);
 
        if (free == 0)
                return;
 
-       sc->sc_tx_desc_tail = tail;
+       que->tx.sc_tx_desc_tail = tail;
 
        if (ifq_is_oactive(&ifp->if_snd))
                ifq_restart(&ifp->if_snd);
@@ -2448,15 +2482,16 @@ em_txeof(struct em_softc *sc)
  *
  **********************************************************************/
 int
-em_get_buf(struct em_softc *sc, int i)
+em_get_buf(struct em_queue *que, int i)
 {
+       struct em_softc *sc = que->sc;
        struct mbuf    *m;
        struct em_packet *pkt;
        struct em_rx_desc *desc;
        int error;
 
-       pkt = &sc->sc_rx_pkts_ring[i];
-       desc = &sc->sc_rx_desc_ring[i];
+       pkt = &que->rx.sc_rx_pkts_ring[i];
+       desc = &que->rx.sc_rx_desc_ring[i];
 
        KASSERT(pkt->pkt_m == NULL);
 
@@ -2497,24 +2532,25 @@ em_get_buf(struct em_softc *sc, int i)
 int
 em_allocate_receive_structures(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct em_packet *pkt;
        int i;
        int error;
 
-       sc->sc_rx_pkts_ring = mallocarray(sc->sc_rx_slots,
-           sizeof(*sc->sc_rx_pkts_ring), M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (sc->sc_rx_pkts_ring == NULL) {
+       que->rx.sc_rx_pkts_ring = mallocarray(sc->sc_rx_slots,
+           sizeof(*que->rx.sc_rx_pkts_ring), M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (que->rx.sc_rx_pkts_ring == NULL) {
                printf("%s: Unable to allocate rx_buffer memory\n", 
                    DEVNAME(sc));
                return (ENOMEM);
        }
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        for (i = 0; i < sc->sc_rx_slots; i++) {
-               pkt = &sc->sc_rx_pkts_ring[i];
+               pkt = &que->rx.sc_rx_pkts_ring[i];
 
                error = bus_dmamap_create(sc->sc_dmat, EM_MCLBYTES, 1,
                    EM_MCLBYTES, 0, BUS_DMA_NOWAIT, &pkt->pkt_map);
@@ -2543,23 +2579,24 @@ fail:
 int
 em_setup_receive_structures(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct ifnet *ifp = &sc->sc_ac.ac_if;
        u_int lwm;
 
-       memset(sc->sc_rx_desc_ring, 0,
-           sc->sc_rx_slots * sizeof(*sc->sc_rx_desc_ring));
-
        if (em_allocate_receive_structures(sc))
                return (ENOMEM);
 
+       memset(que->rx.sc_rx_desc_ring, 0,
+           sc->sc_rx_slots * sizeof(*que->rx.sc_rx_desc_ring));
+
        /* Setup our descriptor pointers */
-       sc->sc_rx_desc_tail = 0;
-       sc->sc_rx_desc_head = sc->sc_rx_slots - 1;
+       que->rx.sc_rx_desc_tail = 0;
+       que->rx.sc_rx_desc_head = sc->sc_rx_slots - 1;
 
        lwm = max(4, 2 * ((ifp->if_hardmtu / MCLBYTES) + 1));
-       if_rxr_init(&sc->sc_rx_ring, lwm, sc->sc_rx_slots);
+       if_rxr_init(&que->rx.sc_rx_ring, lwm, sc->sc_rx_slots);
 
-       if (em_rxfill(sc) == 0) {
+       if (em_rxfill(que) == 0) {
                printf("%s: unable to fill any rx descriptors\n",
                    DEVNAME(sc));
        }
@@ -2575,6 +2612,7 @@ em_setup_receive_structures(struct em_so
 void
 em_initialize_receive_unit(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        u_int32_t       reg_rctl;
        u_int32_t       reg_rxcsum;
        u_int64_t       bus_addr;
@@ -2597,13 +2635,6 @@ em_initialize_receive_unit(struct em_sof
                E1000_WRITE_REG(&sc->hw, ITR, DEFAULT_ITR);
        }
 
-       /* Setup the Base and Length of the Rx Descriptor Ring */
-       bus_addr = sc->sc_rx_dma.dma_map->dm_segs[0].ds_addr;
-       E1000_WRITE_REG(&sc->hw, RDLEN(0),
-           sc->sc_rx_slots * sizeof(*sc->sc_rx_desc_ring));
-       E1000_WRITE_REG(&sc->hw, RDBAH(0), (u_int32_t)(bus_addr >> 32));
-       E1000_WRITE_REG(&sc->hw, RDBAL(0), (u_int32_t)bus_addr);
-
        /* Setup the Receive Control Register */
        reg_rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO |
            E1000_RCTL_RDMTS_HALF |
@@ -2653,22 +2684,29 @@ em_initialize_receive_unit(struct em_sof
        if (sc->hw.mac_type == em_82573)
                E1000_WRITE_REG(&sc->hw, RDTR, 0x20);
 
+       /* Setup the Base and Length of the Rx Descriptor Ring */
+       bus_addr = que->rx.sc_rx_dma.dma_map->dm_segs[0].ds_addr;
+       E1000_WRITE_REG(&sc->hw, RDLEN(que->me),
+           sc->sc_rx_slots * sizeof(*que->rx.sc_rx_desc_ring));
+       E1000_WRITE_REG(&sc->hw, RDBAH(que->me), (u_int32_t)(bus_addr >> 32));
+       E1000_WRITE_REG(&sc->hw, RDBAL(que->me), (u_int32_t)bus_addr);
+
        if (sc->hw.mac_type == em_82575 || sc->hw.mac_type == em_82580 ||
            sc->hw.mac_type == em_82576 ||
            sc->hw.mac_type == em_i210 || sc->hw.mac_type == em_i350) {
                /* 82575/6 need to enable the RX queue */
                uint32_t reg;
-               reg = E1000_READ_REG(&sc->hw, RXDCTL(0));
+               reg = E1000_READ_REG(&sc->hw, RXDCTL(que->me));
                reg |= E1000_RXDCTL_QUEUE_ENABLE;
-               E1000_WRITE_REG(&sc->hw, RXDCTL(0), reg);
+               E1000_WRITE_REG(&sc->hw, RXDCTL(que->me), reg);
        }
 
        /* Enable Receives */
        E1000_WRITE_REG(&sc->hw, RCTL, reg_rctl);
 
        /* Setup the HW Rx Head and Tail Descriptor Pointers */
-       E1000_WRITE_REG(&sc->hw, RDH(0), 0);
-       E1000_WRITE_REG(&sc->hw, RDT(0), sc->sc_rx_desc_head);
+       E1000_WRITE_REG(&sc->hw, RDH(que->me), 0);
+       E1000_WRITE_REG(&sc->hw, RDT(que->me), que->rx.sc_rx_desc_head);
 }
 
 /*********************************************************************
@@ -2679,20 +2717,21 @@ em_initialize_receive_unit(struct em_sof
 void
 em_free_receive_structures(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct em_packet *pkt;
        int i;
 
        INIT_DEBUGOUT("free_receive_structures: begin");
 
-       if_rxr_init(&sc->sc_rx_ring, 0, 0);
+       if_rxr_init(&que->rx.sc_rx_ring, 0, 0);
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
-       if (sc->sc_rx_pkts_ring != NULL) {
+       if (que->rx.sc_rx_pkts_ring != NULL) {
                for (i = 0; i < sc->sc_rx_slots; i++) {
-                       pkt = &sc->sc_rx_pkts_ring[i];
+                       pkt = &que->rx.sc_rx_pkts_ring[i];
                        if (pkt->pkt_m != NULL) {
                                bus_dmamap_sync(sc->sc_dmat, pkt->pkt_map,
                                    0, pkt->pkt_map->dm_mapsize,
@@ -2704,47 +2743,48 @@ em_free_receive_structures(struct em_sof
                        bus_dmamap_destroy(sc->sc_dmat, pkt->pkt_map);
                }
 
-               free(sc->sc_rx_pkts_ring, M_DEVBUF,
-                   sc->sc_rx_slots * sizeof(*sc->sc_rx_pkts_ring));
-               sc->sc_rx_pkts_ring = NULL;
+               free(que->rx.sc_rx_pkts_ring, M_DEVBUF,
+                   sc->sc_rx_slots * sizeof(*que->rx.sc_rx_pkts_ring));
+               que->rx.sc_rx_pkts_ring = NULL;
        }
 
-       if (sc->fmp != NULL) {
-               m_freem(sc->fmp);
-               sc->fmp = NULL;
-               sc->lmp = NULL;
+       if (que->rx.fmp != NULL) {
+               m_freem(que->rx.fmp);
+               que->rx.fmp = NULL;
+               que->rx.lmp = NULL;
        }
 }
 
 int
-em_rxfill(struct em_softc *sc)
+em_rxfill(struct em_queue *que)
 {
+       struct em_softc *sc = que->sc;
        u_int slots;
        int post = 0;
        int i;
 
-       i = sc->sc_rx_desc_head;
+       i = que->rx.sc_rx_desc_head;
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_POSTWRITE);
 
-       for (slots = if_rxr_get(&sc->sc_rx_ring, sc->sc_rx_slots);
+       for (slots = if_rxr_get(&que->rx.sc_rx_ring, sc->sc_rx_slots);
            slots > 0; slots--) {
                if (++i == sc->sc_rx_slots)
                        i = 0;
 
-               if (em_get_buf(sc, i) != 0)
+               if (em_get_buf(que, i) != 0)
                        break;
 
-               sc->sc_rx_desc_head = i;
+               que->rx.sc_rx_desc_head = i;
                post = 1;
        }
 
-       if_rxr_put(&sc->sc_rx_ring, slots);
+       if_rxr_put(&que->rx.sc_rx_ring, slots);
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_PREWRITE);
 
        return (post);
@@ -2753,12 +2793,13 @@ em_rxfill(struct em_softc *sc)
 void
 em_rxrefill(void *arg)
 {
-       struct em_softc *sc = arg;
+       struct em_queue *que = arg;
+       struct em_softc *sc = que->sc;
 
-       if (em_rxfill(sc))
-               E1000_WRITE_REG(&sc->hw, RDT(0), sc->sc_rx_desc_head);
-       else if (if_rxr_inuse(&sc->sc_rx_ring) == 0)
-               timeout_add(&sc->rx_refill, 1);
+       if (em_rxfill(que))
+               E1000_WRITE_REG(&sc->hw, RDT(que->me), que->rx.sc_rx_desc_head);
+       else if (if_rxr_inuse(&que->rx.sc_rx_ring) == 0)
+               timeout_add(&que->rx_refill, 1);
 }
 
 /*********************************************************************
@@ -2769,8 +2810,9 @@ em_rxrefill(void *arg)
  *
  *********************************************************************/
 int
-em_rxeof(struct em_softc *sc)
+em_rxeof(struct em_queue *que)
 {
+       struct em_softc     *sc = que->sc;
        struct ifnet        *ifp = &sc->sc_ac.ac_if;
        struct mbuf_list    ml = MBUF_LIST_INITIALIZER();
        struct mbuf         *m;
@@ -2784,20 +2826,20 @@ em_rxeof(struct em_softc *sc)
        struct em_packet    *pkt;
        u_int8_t            status;
 
-       if (if_rxr_inuse(&sc->sc_rx_ring) == 0)
+       if (if_rxr_inuse(&que->rx.sc_rx_ring) == 0)
                return (0);
 
-       i = sc->sc_rx_desc_tail;
+       i = que->rx.sc_rx_desc_tail;
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_POSTREAD);
 
        do {
                m = NULL;
 
-               pkt = &sc->sc_rx_pkts_ring[i];
-               desc = &sc->sc_rx_desc_ring[i];
+               pkt = &que->rx.sc_rx_pkts_ring[i];
+               desc = &que->rx.sc_rx_desc_ring[i];
 
                status = desc->status;
                if (!ISSET(status, E1000_RXD_STAT_DD))
@@ -2813,7 +2855,7 @@ em_rxeof(struct em_softc *sc)
 
                KASSERT(m != NULL);
 
-               if_rxr_put(&sc->sc_rx_ring, 1);
+               if_rxr_put(&que->rx.sc_rx_ring, 1);
                rv = 1;
 
                accept_frame = 1;
@@ -2839,8 +2881,8 @@ em_rxeof(struct em_softc *sc)
                        u_int8_t last_byte;
                        u_int32_t pkt_len = desc_len;
 
-                       if (sc->fmp != NULL)
-                               pkt_len += sc->fmp->m_pkthdr.len; 
+                       if (que->rx.fmp != NULL)
+                               pkt_len += que->rx.fmp->m_pkthdr.len;
 
                        last_byte = *(mtod(m, caddr_t) + desc_len - 1);
                        if (TBI_ACCEPT(&sc->hw, status, desc->errors,
@@ -2859,10 +2901,10 @@ em_rxeof(struct em_softc *sc)
                        /* Assign correct length to the current fragment */
                        m->m_len = len;
 
-                       if (sc->fmp == NULL) {
+                       if (que->rx.fmp == NULL) {
                                m->m_pkthdr.len = m->m_len;
-                               sc->fmp = m;     /* Store the first mbuf */
-                               sc->lmp = m;
+                               que->rx.fmp = m;         /* Store the first 
mbuf */
+                               que->rx.lmp = m;
                        } else {
                                /* Chain mbuf's together */
                                m->m_flags &= ~M_PKTHDR;
@@ -2872,16 +2914,16 @@ em_rxeof(struct em_softc *sc)
                                 * descriptor.
                                 */
                                if (prev_len_adj > 0) {
-                                       sc->lmp->m_len -= prev_len_adj;
-                                       sc->fmp->m_pkthdr.len -= prev_len_adj;
+                                       que->rx.lmp->m_len -= prev_len_adj;
+                                       que->rx.fmp->m_pkthdr.len -= 
prev_len_adj;
                                }
-                               sc->lmp->m_next = m;
-                               sc->lmp = m;
-                               sc->fmp->m_pkthdr.len += m->m_len;
+                               que->rx.lmp->m_next = m;
+                               que->rx.lmp = m;
+                               que->rx.fmp->m_pkthdr.len += m->m_len;
                        }
 
                        if (eop) {
-                               m = sc->fmp;
+                               m = que->rx.fmp;
 
                                em_receive_checksum(sc, desc, m);
 #if NVLAN > 0
@@ -2893,16 +2935,16 @@ em_rxeof(struct em_softc *sc)
 #endif
                                ml_enqueue(&ml, m);
 
-                               sc->fmp = NULL;
-                               sc->lmp = NULL;
+                               que->rx.fmp = NULL;
+                               que->rx.lmp = NULL;
                        }
                } else {
-                       sc->dropped_pkts++;
+                       que->rx.dropped_pkts++;
 
-                       if (sc->fmp != NULL) {
-                               m_freem(sc->fmp);
-                               sc->fmp = NULL;
-                               sc->lmp = NULL;
+                       if (que->rx.fmp != NULL) {
+                               m_freem(que->rx.fmp);
+                               que->rx.fmp = NULL;
+                               que->rx.lmp = NULL;
                        }
 
                        m_freem(m);
@@ -2911,13 +2953,13 @@ em_rxeof(struct em_softc *sc)
                /* Advance our pointers to the next descriptor. */
                if (++i == sc->sc_rx_slots)
                        i = 0;
-       } while (if_rxr_inuse(&sc->sc_rx_ring) > 0);
+       } while (if_rxr_inuse(&que->rx.sc_rx_ring) > 0);
 
-       bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dma.dma_map,
-           0, sc->sc_rx_dma.dma_map->dm_mapsize,
+       bus_dmamap_sync(sc->sc_dmat, que->rx.sc_rx_dma.dma_map,
+           0, que->rx.sc_rx_dma.dma_map->dm_mapsize,
            BUS_DMASYNC_PREREAD);
 
-       sc->sc_rx_desc_tail = i;
+       que->rx.sc_rx_desc_tail = i;
 
        if_input(ifp, &ml);
 
@@ -3163,21 +3205,22 @@ em_disable_aspm(struct em_softc *sc)
  * to reset the HW.
  */
 void
-em_flush_tx_ring(struct em_softc *sc)
+em_flush_tx_ring(struct em_queue *que)
 {
+       struct em_softc         *sc = que->sc;
        uint32_t                 tctl, txd_lower = E1000_TXD_CMD_IFCS;
        uint16_t                 size = 512;
        struct em_tx_desc       *txd;
 
-       KASSERT(sc->sc_tx_desc_ring != NULL);
+       KASSERT(que->tx.sc_tx_desc_ring != NULL);
 
        tctl = EM_READ_REG(&sc->hw, E1000_TCTL);
        EM_WRITE_REG(&sc->hw, E1000_TCTL, tctl | E1000_TCTL_EN);
 
-       KASSERT(EM_READ_REG(&sc->hw, E1000_TDT(0)) == sc->sc_tx_desc_head);
+       KASSERT(EM_READ_REG(&sc->hw, E1000_TDT(que->me)) == 
que->tx.sc_tx_desc_head);
 
-       txd = &sc->sc_tx_desc_ring[sc->sc_tx_desc_head];
-       txd->buffer_addr = sc->sc_tx_dma.dma_map->dm_segs[0].ds_addr;
+       txd = &que->tx.sc_tx_desc_ring[que->tx.sc_tx_desc_head];
+       txd->buffer_addr = que->tx.sc_tx_dma.dma_map->dm_segs[0].ds_addr;
        txd->lower.data = htole32(txd_lower | size);
        txd->upper.data = 0;
 
@@ -3185,10 +3228,10 @@ em_flush_tx_ring(struct em_softc *sc)
        bus_space_barrier(sc->osdep.mem_bus_space_tag,
            sc->osdep.mem_bus_space_handle, 0, 0, BUS_SPACE_BARRIER_WRITE);
 
-       if (++sc->sc_tx_desc_head == sc->sc_tx_slots)
-               sc->sc_tx_desc_head = 0;
+       if (++que->tx.sc_tx_desc_head == sc->sc_tx_slots)
+               que->tx.sc_tx_desc_head = 0;
 
-       EM_WRITE_REG(&sc->hw, E1000_TDT(0), sc->sc_tx_desc_head);
+       EM_WRITE_REG(&sc->hw, E1000_TDT(que->me), que->tx.sc_tx_desc_head);
        bus_space_barrier(sc->osdep.mem_bus_space_tag, 
sc->osdep.mem_bus_space_handle,
            0, 0, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
        usec_delay(250);
@@ -3200,16 +3243,17 @@ em_flush_tx_ring(struct em_softc *sc)
  * Mark all descriptors in the RX ring as consumed and disable the rx ring
  */
 void
-em_flush_rx_ring(struct em_softc *sc)
+em_flush_rx_ring(struct em_queue *que)
 {
        uint32_t        rctl, rxdctl;
+       struct em_softc *sc = que->sc;
 
        rctl = EM_READ_REG(&sc->hw, E1000_RCTL);
        EM_WRITE_REG(&sc->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
        E1000_WRITE_FLUSH(&sc->hw);
        usec_delay(150);
 
-       rxdctl = EM_READ_REG(&sc->hw, E1000_RXDCTL(0));
+       rxdctl = EM_READ_REG(&sc->hw, E1000_RXDCTL(que->me));
        /* zero the lower 14 bits (prefetch and host thresholds) */
        rxdctl &= 0xffffc000;
        /*
@@ -3217,7 +3261,7 @@ em_flush_rx_ring(struct em_softc *sc)
         * and make sure the granularity is "descriptors" and not "cache lines"
         */
        rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC);
-       EM_WRITE_REG(&sc->hw, E1000_RXDCTL(0), rxdctl);
+       EM_WRITE_REG(&sc->hw, E1000_RXDCTL(que->me), rxdctl);
 
        /* momentarily enable the RX ring for the changes to take effect */
        EM_WRITE_REG(&sc->hw, E1000_RCTL, rctl | E1000_RCTL_EN);
@@ -3239,6 +3283,7 @@ em_flush_rx_ring(struct em_softc *sc)
 void
 em_flush_desc_rings(struct em_softc *sc)
 {
+       struct em_queue         *que = sc->queues; /* Use only first queue. */
        struct pci_attach_args  *pa = &sc->osdep.em_pa;
        uint32_t                 fextnvm11, tdlen;
        uint16_t                 hang_state;
@@ -3249,16 +3294,16 @@ em_flush_desc_rings(struct em_softc *sc)
        EM_WRITE_REG(&sc->hw, E1000_FEXTNVM11, fextnvm11);
 
        /* do nothing if we're not in faulty state, or if the queue is empty */
-       tdlen = EM_READ_REG(&sc->hw, E1000_TDLEN(0));
+       tdlen = EM_READ_REG(&sc->hw, E1000_TDLEN(que->me));
        hang_state = pci_conf_read(pa->pa_pc, pa->pa_tag, 
PCICFG_DESC_RING_STATUS);
        if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen)
                return;
-       em_flush_tx_ring(sc);
+       em_flush_tx_ring(que);
 
        /* recheck, maybe the fault is caused by the rx ring */
        hang_state = pci_conf_read(pa->pa_pc, pa->pa_tag, 
PCICFG_DESC_RING_STATUS);
        if (hang_state & FLUSH_DESC_REQUIRED)
-               em_flush_rx_ring(sc);
+               em_flush_rx_ring(que);
 }
 
 #ifndef SMALL_KERNEL
@@ -3270,6 +3315,7 @@ em_flush_desc_rings(struct em_softc *sc)
 void
 em_update_stats_counters(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
        struct ifnet   *ifp = &sc->sc_ac.ac_if;
 
        sc->stats.crcerrs += E1000_READ_REG(&sc->hw, CRCERRS);
@@ -3370,7 +3416,7 @@ em_update_stats_counters(struct em_softc
 
        /* Rx Errors */
        ifp->if_ierrors =
-           sc->dropped_pkts +
+           que->rx.dropped_pkts +
            sc->stats.rxerrc +
            sc->stats.crcerrs +
            sc->stats.algnerrc +
@@ -3467,23 +3513,27 @@ em_print_hw_stats(struct em_softc *sc)
 int
 em_allocate_desc_rings(struct em_softc *sc)
 {
+       struct em_queue *que = sc->queues; /* Use only first queue. */
+
        /* Allocate Transmit Descriptor ring */
        if (em_dma_malloc(sc, sc->sc_tx_slots * sizeof(struct em_tx_desc),
-           &sc->sc_tx_dma) != 0) {
+           &que->tx.sc_tx_dma) != 0) {
                printf("%s: Unable to allocate tx_desc memory\n", 
                       DEVNAME(sc));
                return (ENOMEM);
        }
-       sc->sc_tx_desc_ring = (struct em_tx_desc *)sc->sc_tx_dma.dma_vaddr;
+       que->tx.sc_tx_desc_ring =
+           (struct em_tx_desc *)que->tx.sc_tx_dma.dma_vaddr;
 
        /* Allocate Receive Descriptor ring */
        if (em_dma_malloc(sc, sc->sc_rx_slots * sizeof(struct em_rx_desc),
-           &sc->sc_rx_dma) != 0) {
+           &que->rx.sc_rx_dma) != 0) {
                printf("%s: Unable to allocate rx_desc memory\n",
                       DEVNAME(sc));
                return (ENOMEM);
        }
-       sc->sc_rx_desc_ring = (struct em_rx_desc *)sc->sc_rx_dma.dma_vaddr;
+       que->rx.sc_rx_desc_ring =
+           (struct em_rx_desc *)que->rx.sc_rx_dma.dma_vaddr;
 
        return (0);
 }
Index: dev/pci/if_em.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em.h,v
retrieving revision 1.74
diff -u -p -r1.74 if_em.h
--- dev/pci/if_em.h     1 Mar 2019 10:02:44 -0000       1.74
+++ dev/pci/if_em.h     13 Feb 2020 13:27:01 -0000
@@ -305,6 +305,66 @@ typedef struct _DESCRIPTOR_PAIR
        u_int32_t       elements;
 } DESC_ARRAY, *PDESC_ARRAY;
 
+/*
+ * Receive definitions
+ *
+ * we have an array of num_rx_desc rx_desc (handled by the
+ * controller), and paired with an array of rx_buffers
+ * (at rx_buffer_area).
+ * The next pair to check on receive is at offset next_rx_desc_to_check
+ */
+struct em_rx {
+       struct em_dma_alloc      sc_rx_dma;     /* bus_dma glue for rx desc */
+       struct em_rx_desc       *sc_rx_desc_ring;
+       u_int                    sc_rx_desc_head;
+       u_int                    sc_rx_desc_tail;
+       struct em_packet        *sc_rx_pkts_ring;
+
+       struct if_rxring         sc_rx_ring;
+
+       /*
+        * First/last mbuf pointers, for
+        * collecting multisegment RX packets.
+        */
+       struct mbuf             *fmp;
+       struct mbuf             *lmp;
+
+       /* Statistics */
+       unsigned long           dropped_pkts;
+};
+
+/*
+ * Transmit definitions
+ *
+ * We have an array of num_tx_desc descriptors (handled
+ * by the controller) paired with an array of tx_buffers
+ * (at tx_buffer_area).
+ * The index of the next available descriptor is next_avail_tx_desc.
+ * The number of remaining tx_desc is num_tx_desc_avail.
+ */
+struct em_tx {
+       struct em_dma_alloc      sc_tx_dma;     /* bus_dma glue for tx desc */
+       struct em_tx_desc       *sc_tx_desc_ring;
+       u_int                    sc_tx_desc_head;
+       u_int                    sc_tx_desc_tail;
+       struct em_packet        *sc_tx_pkts_ring;
+
+       u_int32_t                sc_txd_cmd;
+
+       XSUM_CONTEXT_T           active_checksum_context;
+};
+
+struct em_softc;
+struct em_queue {
+       struct em_softc         *sc;
+       uint32_t                 me;    /* queue index, also msix vector */
+
+       struct em_tx             tx;
+       struct em_rx             rx;
+
+       struct timeout           rx_refill;
+};
+
 /* Our adapter structure */
 struct em_softc {
        struct device   sc_dev;
@@ -324,7 +384,6 @@ struct em_softc {
        struct timeout  em_intr_enable;
        struct timeout  timer_handle;
        struct timeout  tx_fifo_timer_handle;
-       struct timeout  rx_refill;
 
        /* Info about the board itself */
        u_int32_t       part_num;
@@ -337,53 +396,11 @@ struct em_softc {
        u_int32_t       rx_int_delay;
        u_int32_t       rx_abs_int_delay;
 
-       XSUM_CONTEXT_T  active_checksum_context;
-
-       /*
-        * Transmit definitions
-        *
-        * We have an array of num_tx_desc descriptors (handled
-        * by the controller) paired with an array of tx_buffers
-        * (at tx_buffer_area).
-        * The index of the next available descriptor is next_avail_tx_desc.
-        * The number of remaining tx_desc is num_tx_desc_avail.
-        */
        u_int                    sc_tx_slots;
-       struct em_dma_alloc      sc_tx_dma;     /* bus_dma glue for tx desc */
-       struct em_tx_desc       *sc_tx_desc_ring;
-       u_int                    sc_tx_desc_head;
-       u_int                    sc_tx_desc_tail;
-       struct em_packet        *sc_tx_pkts_ring;
-
-       u_int32_t                sc_txd_cmd;
-
-       /*
-        * Receive definitions
-        *
-        * we have an array of num_rx_desc rx_desc (handled by the
-        * controller), and paired with an array of rx_buffers
-        * (at rx_buffer_area).
-        * The next pair to check on receive is at offset next_rx_desc_to_check
-        */
        u_int                    sc_rx_slots;
-       struct if_rxring         sc_rx_ring;
-       struct em_dma_alloc      sc_rx_dma;     /* bus_dma glue for rx desc */
-       struct em_rx_desc       *sc_rx_desc_ring;
-       u_int                    sc_rx_desc_head;
-       u_int                    sc_rx_desc_tail;
-       struct em_packet        *sc_rx_pkts_ring;
-
        u_int32_t                sc_rx_buffer_len;
 
-       /*
-        * First/last mbuf pointers, for
-        * collecting multisegment RX packets.
-        */
-       struct mbuf             *fmp;
-       struct mbuf             *lmp;
-
        /* Misc stats maintained by the driver */
-       unsigned long           dropped_pkts;
        unsigned long           mbuf_alloc_failed;
        unsigned long           mbuf_cluster_failed;
        unsigned long           no_tx_desc_avail1;
@@ -401,6 +418,10 @@ struct em_softc {
 
        #define EM_82547_PKT_THRESH     0x3e0
 
+       /*
+        * These are all 82547 members for the workaround. The chip is pretty
+        * old, single queue, so keep it here to avoid further changes.
+        */
        u_int32_t       tx_fifo_size;
        u_int32_t       tx_fifo_head;
        u_int32_t       tx_fifo_head_addr;
@@ -411,6 +432,9 @@ struct em_softc {
        /* For 82544 PCI-X Workaround */
        boolean_t       pcix_82544;
        struct em_hw_stats stats;
+
+       int                      num_queues;
+       struct em_queue         *queues;
 };
 
 #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)

Reply via email to