[PATCH] e1000: Delay clean-up of last Tx buffer
Linux Kernel Mailing List <[email protected]> Thu, 24 Feb 2005 05:40:46 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1548.1.4, 2005/02/24 00:40:46-05:00, [email protected] [PATCH] e1000: Delay clean-up of last Tx buffer 4 Delay clean-up of last Tx buffer to fix pre-mature writeback of Tx descriptors. Signed-off-by: Mallikarjuna R Chilakala <[email protected]> Signed-off-by: Ganesh Venkatesan <[email protected]> Signed-off-by: John Ronciak <[email protected]> Signed-off-by: Jeff Garzik <[email protected]> e1000.h | 1 + e1000_main.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h 2005-03-04 12:02:51 -08:00 +++ b/drivers/net/e1000/e1000.h 2005-03-04 12:02:51 -08:00 @@ -211,6 +211,7 @@ /* TX */ struct e1000_desc_ring tx_ring; + struct e1000_buffer previous_buffer_info; spinlock_t tx_lock; uint32_t txd_cmd; uint32_t tx_int_delay; diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2005-03-04 12:02:51 -08:00 +++ b/drivers/net/e1000/e1000_main.c 2005-03-04 12:02:51 -08:00 @@ -1093,6 +1093,7 @@ struct e1000_buffer *buffer_info) { struct pci_dev *pdev = adapter->pdev; + if(buffer_info->dma) { pci_unmap_page(pdev, buffer_info->dma, @@ -1121,6 +1122,11 @@ /* Free all the Tx ring sk_buffs */ + if (likely(adapter->previous_buffer_info.skb != NULL)) { + e1000_unmap_and_free_tx_resource(adapter, + &adapter->previous_buffer_info); + } + for(i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); @@ -2195,11 +2201,34 @@ eop_desc = E1000_TX_DESC(*tx_ring, eop); while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { + /* pre-mature writeback of Tx descriptors */ + /* clear (free buffers and unmap pci_mapping) */ + /* previous_buffer_info */ + if (likely(adapter->previous_buffer_info.skb != NULL)) { + e1000_unmap_and_free_tx_resource(adapter, + &adapter->previous_buffer_info); + } + for(cleaned = FALSE; !cleaned; ) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; + cleaned = (i == eop); + + /* pre-mature writeback of Tx descriptors */ + /* save the cleaning of the this for the */ + /* next iteration */ + if (cleaned) { + memcpy(&adapter->previous_buffer_info, + buffer_info, + sizeof(struct e1000_buffer)); + memset(buffer_info, + 0, + sizeof(struct e1000_buffer)); + } else { + e1000_unmap_and_free_tx_resource(adapter, + buffer_info); + } - e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->buffer_addr = 0; tx_desc->lower.data = 0; tx_desc->upper.data = 0;