diff options
| author | Gleb Smirnoff <glebius@FreeBSD.org> | 2006-10-31 16:19:21 +0000 |
|---|---|---|
| committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2006-10-31 16:19:21 +0000 |
| commit | 72f0301fef026d7ce49f90b72cf2bafde2f5c30e (patch) | |
| tree | b3aabaa003e99ecc5a5d33857bfe43b10c3b0882 /sys/dev/em | |
| parent | 223eee05e497cbe73cd07ebda5d98b14d8197e1c (diff) | |
Notes
Diffstat (limited to 'sys/dev/em')
| -rw-r--r-- | sys/dev/em/if_em.c | 109 | ||||
| -rw-r--r-- | sys/dev/em/if_em.h | 3 |
2 files changed, 79 insertions, 33 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index 0803ce775e2f8..803341ee15820 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -1464,11 +1464,11 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) struct ifnet *ifp = adapter->ifp; bus_dma_segment_t segs[EM_MAX_SCATTER]; bus_dmamap_t map; - struct em_buffer *tx_buffer, *tx_buffer_last; + struct em_buffer *tx_buffer, *tx_buffer_mapped; struct em_tx_desc *current_tx_desc; struct mbuf *m_head; uint32_t txd_upper, txd_lower, txd_used, txd_saved; - int nsegs, i, j; + int nsegs, i, j, first, last = 0; int error, do_tso, tso_desc = 0; m_head = *m_headp; @@ -1543,9 +1543,15 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) /* * Map the packet for DMA. + * + * Capture the first descriptor index, + * this descriptor will have the index + * of the EOP which is the only one that + * now gets a DONE bit writeback. */ - tx_buffer = &adapter->tx_buffer_area[adapter->next_avail_tx_desc]; - tx_buffer_last = tx_buffer; + first = adapter->next_avail_tx_desc; + tx_buffer = &adapter->tx_buffer_area[first]; + tx_buffer_mapped = tx_buffer; map = tx_buffer->map; error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, *m_headp, segs, @@ -1658,10 +1664,12 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) (adapter->txd_cmd | txd_lower | (uint16_t)desc_array.descriptor[counter].length)); current_tx_desc->upper.data = htole32((txd_upper)); + last = i; if (++i == adapter->num_tx_desc) i = 0; tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; txd_used++; } } else { @@ -1693,6 +1701,7 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) adapter->txd_cmd | txd_lower | 4); current_tx_desc->upper.data = htole32(txd_upper); + last = i; if (++i == adapter->num_tx_desc) i = 0; } else { @@ -1701,10 +1710,12 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) adapter->txd_cmd | txd_lower | seg_len); current_tx_desc->upper.data = htole32(txd_upper); + last = i; if (++i == adapter->num_tx_desc) i = 0; } tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; } } @@ -1727,14 +1738,23 @@ em_encap(struct adapter *adapter, struct mbuf **m_headp) } tx_buffer->m_head = m_head; - tx_buffer_last->map = tx_buffer->map; + tx_buffer_mapped->map = tx_buffer->map; tx_buffer->map = map; bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE); /* - * Last Descriptor of Packet needs End Of Packet (EOP). + * Last Descriptor of Packet + * needs End Of Packet (EOP) + * and Report Status (RS) + */ + current_tx_desc->lower.data |= + htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); + /* + * Keep track in the first buffer which + * descriptor will be written back */ - current_tx_desc->lower.data |= htole32(E1000_TXD_CMD_EOP); + tx_buffer = &adapter->tx_buffer_area[first]; + tx_buffer->next_eop = last; /* * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000 @@ -2653,7 +2673,7 @@ em_setup_transmit_structures(struct adapter *adapter) } adapter->next_avail_tx_desc = 0; - adapter->oldest_used_tx_desc = 0; + adapter->next_tx_to_clean = 0; /* Set number of descriptors available */ adapter->num_tx_desc_avail = adapter->num_tx_desc; @@ -2739,8 +2759,8 @@ em_initialize_transmit_unit(struct adapter *adapter) /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(&adapter->hw, TCTL, reg_tctl); - /* Setup Transmit Descriptor Settings for this adapter */ - adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_RS; + /* Setup Transmit Descriptor Base Settings */ + adapter->txd_cmd = E1000_TXD_CMD_IFCS; if (adapter->tx_int_delay.value > 0) adapter->txd_cmd |= E1000_TXD_CMD_IDE; @@ -2923,6 +2943,7 @@ em_transmit_checksum_setup(struct adapter *adapter, struct mbuf *mp, TXD->cmd_and_length = htole32(adapter->txd_cmd | E1000_TXD_CMD_DEXT | cmd); tx_buffer->m_head = NULL; + tx_buffer->next_eop = -1; if (++curr_txd == adapter->num_tx_desc) curr_txd = 0; @@ -3099,9 +3120,9 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp, uint32_t *txd_upper, static void em_txeof(struct adapter *adapter) { - int i, num_avail; + int first, last, done, num_avail; struct em_buffer *tx_buffer; - struct em_tx_desc *tx_desc; + struct em_tx_desc *tx_desc, *eop_desc; struct ifnet *ifp = adapter->ifp; EM_LOCK_ASSERT(adapter); @@ -3110,38 +3131,62 @@ em_txeof(struct adapter *adapter) return; num_avail = adapter->num_tx_desc_avail; - i = adapter->oldest_used_tx_desc; + first = adapter->next_tx_to_clean; + tx_desc = &adapter->tx_desc_base[first]; + tx_buffer = &adapter->tx_buffer_area[first]; + last = tx_buffer->next_eop; + eop_desc = &adapter->tx_desc_base[last]; - tx_buffer = &adapter->tx_buffer_area[i]; - tx_desc = &adapter->tx_desc_base[i]; + /* + * Now calculate the terminating index + * for the cleanup loop below. + */ + if (++last == adapter->num_tx_desc) + last = 0; + done = last; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_POSTREAD); - while (tx_desc->upper.fields.status & E1000_TXD_STAT_DD) { + while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { + /* We clean the range of the packet */ + while (first != done) { + tx_desc->upper.data = 0; + tx_desc->lower.data = 0; + num_avail++; - tx_desc->upper.data = 0; - num_avail++; - - if (tx_buffer->m_head) { - ifp->if_opackets++; - bus_dmamap_sync(adapter->txtag, tx_buffer->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(adapter->txtag, tx_buffer->map); + if (tx_buffer->m_head) { + ifp->if_opackets++; + bus_dmamap_sync(adapter->txtag, tx_buffer->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(adapter->txtag, + tx_buffer->map); - m_freem(tx_buffer->m_head); - tx_buffer->m_head = NULL; - } + m_freem(tx_buffer->m_head); + tx_buffer->m_head = NULL; + } + tx_buffer->next_eop = -1; - if (++i == adapter->num_tx_desc) - i = 0; + if (++first == adapter->num_tx_desc) + first = 0; - tx_buffer = &adapter->tx_buffer_area[i]; - tx_desc = &adapter->tx_desc_base[i]; + tx_buffer = &adapter->tx_buffer_area[first]; + tx_desc = &adapter->tx_desc_base[first]; + } + /* See if we can continue to the next packet */ + last = tx_buffer->next_eop; + if (last != -1) { + eop_desc = &adapter->tx_desc_base[last]; + /* Get new done point */ + if (++last == adapter->num_tx_desc) + last = 0; + done = last; + } else + break; } bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - adapter->oldest_used_tx_desc = i; + adapter->next_tx_to_clean = first; /* * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack diff --git a/sys/dev/em/if_em.h b/sys/dev/em/if_em.h index 27f664e48fd10..33752c0a78b0f 100644 --- a/sys/dev/em/if_em.h +++ b/sys/dev/em/if_em.h @@ -319,7 +319,7 @@ struct adapter { struct em_dma_alloc txdma; /* bus_dma glue for tx desc */ struct em_tx_desc *tx_desc_base; uint32_t next_avail_tx_desc; - uint32_t oldest_used_tx_desc; + uint32_t next_tx_to_clean; volatile uint16_t num_tx_desc_avail; uint16_t num_tx_desc; uint32_t txd_cmd; @@ -398,6 +398,7 @@ typedef struct _em_vendor_info_t { struct em_buffer { + int next_eop; /* Index of the desc to watch */ struct mbuf *m_head; bus_dmamap_t map; /* bus_dma map for packet */ }; |
