aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/falcon.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-03-20 09:30:37 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-21 22:06:58 -0400
commit6fb70fd1b57707a5c7b9fb167b7790b2cba13f04 (patch)
tree311192bd4de07e1da571f1a6ac6a3ad123ab3f50 /drivers/net/sfc/falcon.c
parent85451a951b9511605475fadcc0a8d3aeccefded8 (diff)
sfc: Implement adaptive IRQ moderation
Calculate a score for each 1000 IRQs: - TX completions are worth 1 point - RX completions are worth 4 if merged using LRO or 2 otherwise Reduce moderation if the score is less than 10000, down to a minimum of 5 us. Increase moderation if the score is more than 20000, up to the specified maximum. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r--drivers/net/sfc/falcon.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index f42fc60d1df4..23a1b148d5b2 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -729,6 +729,9 @@ static void falcon_handle_tx_event(struct efx_channel *channel,
729 tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR); 729 tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR);
730 tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); 730 tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL);
731 tx_queue = &efx->tx_queue[tx_ev_q_label]; 731 tx_queue = &efx->tx_queue[tx_ev_q_label];
732 channel->irq_mod_score +=
733 (tx_ev_desc_ptr - tx_queue->read_count) &
734 efx->type->txd_ring_mask;
732 efx_xmit_done(tx_queue, tx_ev_desc_ptr); 735 efx_xmit_done(tx_queue, tx_ev_desc_ptr);
733 } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) { 736 } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) {
734 /* Rewrite the FIFO write pointer */ 737 /* Rewrite the FIFO write pointer */
@@ -898,6 +901,8 @@ static void falcon_handle_rx_event(struct efx_channel *channel,
898 discard = true; 901 discard = true;
899 } 902 }
900 903
904 channel->irq_mod_score += 2;
905
901 /* Handle received packet */ 906 /* Handle received packet */
902 efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, 907 efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
903 checksummed, discard); 908 checksummed, discard);
@@ -1075,14 +1080,15 @@ void falcon_set_int_moderation(struct efx_channel *channel)
1075 * program is based at 0. So actual interrupt moderation 1080 * program is based at 0. So actual interrupt moderation
1076 * achieved is ((x + 1) * res). 1081 * achieved is ((x + 1) * res).
1077 */ 1082 */
1078 unsigned int res = 5; 1083 channel->irq_moderation -= (channel->irq_moderation %
1079 channel->irq_moderation -= (channel->irq_moderation % res); 1084 FALCON_IRQ_MOD_RESOLUTION);
1080 if (channel->irq_moderation < res) 1085 if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION)
1081 channel->irq_moderation = res; 1086 channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION;
1082 EFX_POPULATE_DWORD_2(timer_cmd, 1087 EFX_POPULATE_DWORD_2(timer_cmd,
1083 TIMER_MODE, TIMER_MODE_INT_HLDOFF, 1088 TIMER_MODE, TIMER_MODE_INT_HLDOFF,
1084 TIMER_VAL, 1089 TIMER_VAL,
1085 (channel->irq_moderation / res) - 1); 1090 channel->irq_moderation /
1091 FALCON_IRQ_MOD_RESOLUTION - 1);
1086 } else { 1092 } else {
1087 EFX_POPULATE_DWORD_2(timer_cmd, 1093 EFX_POPULATE_DWORD_2(timer_cmd,
1088 TIMER_MODE, TIMER_MODE_DIS, 1094 TIMER_MODE, TIMER_MODE_DIS,