diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2012-09-13 02:28:01 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-09-22 05:50:24 -0400 |
commit | f4128785b8f3f1fd7dc81b972661003d639a4676 (patch) | |
tree | 8d34f8c4b12cf6032fe135d073319c94af96c79c /drivers | |
parent | f33005a637bffca72fe373d1e91f2dfbc8fae157 (diff) |
igb: Change Tx cleanup loop to do/while instead of for
This change makes it so that Tx cleanup is done in a do/while loop instead
of a for loop. The main motivation behind this is the fact that we should
never be invoked with a budget less than 1 so we can skip checking the
budget before processing the first descriptor.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index c9997d83de07..91f542c50f61 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -5690,7 +5690,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5690 | struct igb_adapter *adapter = q_vector->adapter; | 5690 | struct igb_adapter *adapter = q_vector->adapter; |
5691 | struct igb_ring *tx_ring = q_vector->tx.ring; | 5691 | struct igb_ring *tx_ring = q_vector->tx.ring; |
5692 | struct igb_tx_buffer *tx_buffer; | 5692 | struct igb_tx_buffer *tx_buffer; |
5693 | union e1000_adv_tx_desc *tx_desc, *eop_desc; | 5693 | union e1000_adv_tx_desc *tx_desc; |
5694 | unsigned int total_bytes = 0, total_packets = 0; | 5694 | unsigned int total_bytes = 0, total_packets = 0; |
5695 | unsigned int budget = q_vector->tx.work_limit; | 5695 | unsigned int budget = q_vector->tx.work_limit; |
5696 | unsigned int i = tx_ring->next_to_clean; | 5696 | unsigned int i = tx_ring->next_to_clean; |
@@ -5702,16 +5702,16 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5702 | tx_desc = IGB_TX_DESC(tx_ring, i); | 5702 | tx_desc = IGB_TX_DESC(tx_ring, i); |
5703 | i -= tx_ring->count; | 5703 | i -= tx_ring->count; |
5704 | 5704 | ||
5705 | for (; budget; budget--) { | 5705 | do { |
5706 | eop_desc = tx_buffer->next_to_watch; | 5706 | union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; |
5707 | |||
5708 | /* prevent any other reads prior to eop_desc */ | ||
5709 | rmb(); | ||
5710 | 5707 | ||
5711 | /* if next_to_watch is not set then there is no work pending */ | 5708 | /* if next_to_watch is not set then there is no work pending */ |
5712 | if (!eop_desc) | 5709 | if (!eop_desc) |
5713 | break; | 5710 | break; |
5714 | 5711 | ||
5712 | /* prevent any other reads prior to eop_desc */ | ||
5713 | rmb(); | ||
5714 | |||
5715 | /* if DD is not set pending work has not been completed */ | 5715 | /* if DD is not set pending work has not been completed */ |
5716 | if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) | 5716 | if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) |
5717 | break; | 5717 | break; |
@@ -5767,7 +5767,13 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5767 | tx_buffer = tx_ring->tx_buffer_info; | 5767 | tx_buffer = tx_ring->tx_buffer_info; |
5768 | tx_desc = IGB_TX_DESC(tx_ring, 0); | 5768 | tx_desc = IGB_TX_DESC(tx_ring, 0); |
5769 | } | 5769 | } |
5770 | } | 5770 | |
5771 | /* issue prefetch for next Tx descriptor */ | ||
5772 | prefetch(tx_desc); | ||
5773 | |||
5774 | /* update budget accounting */ | ||
5775 | budget--; | ||
5776 | } while (likely(budget)); | ||
5771 | 5777 | ||
5772 | netdev_tx_completed_queue(txring_txq(tx_ring), | 5778 | netdev_tx_completed_queue(txring_txq(tx_ring), |
5773 | total_packets, total_bytes); | 5779 | total_packets, total_bytes); |
@@ -5783,12 +5789,10 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5783 | if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { | 5789 | if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { |
5784 | struct e1000_hw *hw = &adapter->hw; | 5790 | struct e1000_hw *hw = &adapter->hw; |
5785 | 5791 | ||
5786 | eop_desc = tx_buffer->next_to_watch; | ||
5787 | |||
5788 | /* Detect a transmit hang in hardware, this serializes the | 5792 | /* Detect a transmit hang in hardware, this serializes the |
5789 | * check with the clearing of time_stamp and movement of i */ | 5793 | * check with the clearing of time_stamp and movement of i */ |
5790 | clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); | 5794 | clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); |
5791 | if (eop_desc && | 5795 | if (tx_buffer->next_to_watch && |
5792 | time_after(jiffies, tx_buffer->time_stamp + | 5796 | time_after(jiffies, tx_buffer->time_stamp + |
5793 | (adapter->tx_timeout_factor * HZ)) && | 5797 | (adapter->tx_timeout_factor * HZ)) && |
5794 | !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { | 5798 | !(rd32(E1000_STATUS) & E1000_STATUS_TXOFF)) { |
@@ -5812,9 +5816,9 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5812 | tx_ring->next_to_use, | 5816 | tx_ring->next_to_use, |
5813 | tx_ring->next_to_clean, | 5817 | tx_ring->next_to_clean, |
5814 | tx_buffer->time_stamp, | 5818 | tx_buffer->time_stamp, |
5815 | eop_desc, | 5819 | tx_buffer->next_to_watch, |
5816 | jiffies, | 5820 | jiffies, |
5817 | eop_desc->wb.status); | 5821 | tx_buffer->next_to_watch->wb.status); |
5818 | netif_stop_subqueue(tx_ring->netdev, | 5822 | netif_stop_subqueue(tx_ring->netdev, |
5819 | tx_ring->queue_index); | 5823 | tx_ring->queue_index); |
5820 | 5824 | ||