em: Don't update TDT upon very packets transmitted
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 28 Dec 2012 07:12:02 +0000 (15:12 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 28 Dec 2012 07:12:02 +0000 (15:12 +0800)
Merged following commits on emx(4):
7f32a9b0f8f25e43ab2ae4ee0d82ce69325d3b4b
0aba36eb844503423f414a3235eca72a78dc575a
b691889cfe23462069618f44bcf2ba0e71dcbb79

With following exception:
This optimization is not performed for 82547

sys/dev/netif/em/if_em.c
sys/dev/netif/em/if_em.h

index bbc430e..90d8df8 100644 (file)
@@ -295,7 +295,7 @@ static int  em_create_rx_ring(struct adapter *);
 static void    em_destroy_tx_ring(struct adapter *, int);
 static void    em_destroy_rx_ring(struct adapter *, int);
 static int     em_newbuf(struct adapter *, int, int);
-static int     em_encap(struct adapter *, struct mbuf **);
+static int     em_encap(struct adapter *, struct mbuf **, int *, int *);
 static void    em_rxcsum(struct adapter *, struct e1000_rx_desc *,
                    struct mbuf *);
 static int     em_txcsum(struct adapter *, struct mbuf *,
@@ -822,6 +822,7 @@ em_attach(device_t dev)
        }
        if (adapter->flags & EM_FLAG_TSO)
                adapter->spare_tx_desc = EM_TX_SPARE_TSO;
+       adapter->tx_wreg_nsegs = 8;
 
        /*
         * Keep following relationship between spare_tx_desc, oact_tx_desc
@@ -991,6 +992,7 @@ em_start(struct ifnet *ifp)
 {
        struct adapter *adapter = ifp->if_softc;
        struct mbuf *m_head;
+       int idx = -1, nsegs = 0;
 
        ASSERT_SERIALIZED(ifp->if_serializer);
 
@@ -1018,18 +1020,26 @@ em_start(struct ifnet *ifp)
                if (m_head == NULL)
                        break;
 
-               if (em_encap(adapter, &m_head)) {
+               if (em_encap(adapter, &m_head, &nsegs, &idx)) {
                        ifp->if_oerrors++;
                        em_tx_collect(adapter);
                        continue;
                }
 
+               if (nsegs >= adapter->tx_wreg_nsegs && idx >= 0) {
+                       E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), idx);
+                       nsegs = 0;
+                       idx = -1;
+               }
+
                /* Send a copy of the frame to the BPF listener */
                ETHER_BPF_MTAP(ifp, m_head);
 
                /* Set timeout in case hardware has problems transmitting. */
                ifp->if_timer = EM_TX_TIMEOUT;
        }
+       if (idx >= 0)
+               E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), idx);
 }
 
 static int
@@ -1646,7 +1656,8 @@ em_media_change(struct ifnet *ifp)
 }
 
 static int
-em_encap(struct adapter *adapter, struct mbuf **m_headp)
+em_encap(struct adapter *adapter, struct mbuf **m_headp,
+    int *segs_used, int *idx)
 {
        bus_dma_segment_t segs[EM_MAX_SCATTER];
        bus_dmamap_t map;
@@ -1702,15 +1713,18 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
 
        m_head = *m_headp;
        adapter->tx_nsegs += nsegs;
+       *segs_used += nsegs;
 
        if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
                /* TSO will consume one TX desc */
-               adapter->tx_nsegs += em_tso_setup(adapter, m_head,
-                   &txd_upper, &txd_lower);
+               i = em_tso_setup(adapter, m_head, &txd_upper, &txd_lower);
+               adapter->tx_nsegs += i;
+               *segs_used += i;
        } else if (m_head->m_pkthdr.csum_flags & EM_CSUM_FEATURES) {
                /* TX csum offloading will consume one TX desc */
-               adapter->tx_nsegs += em_txcsum(adapter, m_head,
-                                              &txd_upper, &txd_lower);
+               i = em_txcsum(adapter, m_head, &txd_upper, &txd_lower);
+               adapter->tx_nsegs += i;
+               *segs_used += i;
        }
        i = adapter->next_avail_tx_desc;
 
@@ -1807,19 +1821,23 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp)
         */
        ctxd->lower.data |= htole32(E1000_TXD_CMD_EOP | cmd);
 
-       /*
-        * Advance the Transmit Descriptor Tail (TDT), this tells the E1000
-        * that this frame is available to transmit.
-        */
-       if (adapter->hw.mac.type == e1000_82547 &&
-           adapter->link_duplex == HALF_DUPLEX) {
-               em_82547_move_tail_serialized(adapter);
-       } else {
-               E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i);
-               if (adapter->hw.mac.type == e1000_82547) {
+       if (adapter->hw.mac.type == e1000_82547) {
+               /*
+                * Advance the Transmit Descriptor Tail (TDT), this tells the
+                * E1000 that this frame is available to transmit.
+                */
+               if (adapter->link_duplex == HALF_DUPLEX) {
+                       em_82547_move_tail_serialized(adapter);
+               } else {
+                       E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), i);
                        em_82547_update_fifo_head(adapter,
                            m_head->m_pkthdr.len);
                }
+       } else {
+               /*
+                * Defer TDT updating, until enough descriptors are setup
+                */
+               *idx = i;
        }
        return (0);
 }
@@ -4042,6 +4060,11 @@ em_add_sysctl(struct adapter *adapter)
                    CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
                    em_sysctl_int_tx_nsegs, "I",
                    "# segments per TX interrupt");
+               SYSCTL_ADD_INT(&adapter->sysctl_ctx,
+                   SYSCTL_CHILDREN(adapter->sysctl_tree),
+                   OID_AUTO, "wreg_tx_nsegs", CTLFLAG_RW,
+                   &adapter->tx_wreg_nsegs, 0,
+                   "# segments before write to hardware register");
        }
 }
 
index 5ac729f..b159ddf 100644 (file)
@@ -327,6 +327,8 @@ struct adapter {
        uint32_t                csum_txd_upper;
        uint32_t                csum_txd_lower;
 
+       int                     tx_wreg_nsegs;
+
        /*
         * Variables used to reduce TX interrupt rate and
         * number of device's TX ring write requests.