aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-04-28 05:29:42 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-28 15:44:39 -0400
commitfa236e18047ec178b07fdf3f24f286eef1797842 (patch)
tree75b7222d666c5d7d71c153503d1ce6890e901e1f /drivers/net/sfc
parent3a595102d4298a357d70aaf1d47ae86d92708ea9 (diff)
sfc: Break NAPI processing after one ring-full of TX completions
Currently TX completions do not count towards the NAPI budget. This means a continuous stream of TX completions can cause the polling function to loop indefinitely with scheduling disabled. To avoid this, follow the common practice of reporting the budget spent after processing one ring-full of TX completions. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c18
-rw-r--r--drivers/net/sfc/nic.c39
2 files changed, 33 insertions, 24 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 1ad61b7bba40..5e3f944fdd95 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -225,17 +225,17 @@ static void efx_fini_channels(struct efx_nic *efx);
225 * never be concurrently called more than once on the same channel, 225 * never be concurrently called more than once on the same channel,
226 * though different channels may be being processed concurrently. 226 * though different channels may be being processed concurrently.
227 */ 227 */
228static int efx_process_channel(struct efx_channel *channel, int rx_quota) 228static int efx_process_channel(struct efx_channel *channel, int budget)
229{ 229{
230 struct efx_nic *efx = channel->efx; 230 struct efx_nic *efx = channel->efx;
231 int rx_packets; 231 int spent;
232 232
233 if (unlikely(efx->reset_pending != RESET_TYPE_NONE || 233 if (unlikely(efx->reset_pending != RESET_TYPE_NONE ||
234 !channel->enabled)) 234 !channel->enabled))
235 return 0; 235 return 0;
236 236
237 rx_packets = efx_nic_process_eventq(channel, rx_quota); 237 spent = efx_nic_process_eventq(channel, budget);
238 if (rx_packets == 0) 238 if (spent == 0)
239 return 0; 239 return 0;
240 240
241 /* Deliver last RX packet. */ 241 /* Deliver last RX packet. */
@@ -249,7 +249,7 @@ static int efx_process_channel(struct efx_channel *channel, int rx_quota)
249 249
250 efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]); 250 efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
251 251
252 return rx_packets; 252 return spent;
253} 253}
254 254
255/* Mark channel as finished processing 255/* Mark channel as finished processing
@@ -278,14 +278,14 @@ static int efx_poll(struct napi_struct *napi, int budget)
278{ 278{
279 struct efx_channel *channel = 279 struct efx_channel *channel =
280 container_of(napi, struct efx_channel, napi_str); 280 container_of(napi, struct efx_channel, napi_str);
281 int rx_packets; 281 int spent;
282 282
283 EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n", 283 EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
284 channel->channel, raw_smp_processor_id()); 284 channel->channel, raw_smp_processor_id());
285 285
286 rx_packets = efx_process_channel(channel, budget); 286 spent = efx_process_channel(channel, budget);
287 287
288 if (rx_packets < budget) { 288 if (spent < budget) {
289 struct efx_nic *efx = channel->efx; 289 struct efx_nic *efx = channel->efx;
290 290
291 if (channel->used_flags & EFX_USED_BY_RX && 291 if (channel->used_flags & EFX_USED_BY_RX &&
@@ -318,7 +318,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
318 efx_channel_processed(channel); 318 efx_channel_processed(channel);
319 } 319 }
320 320
321 return rx_packets; 321 return spent;
322} 322}
323 323
324/* Process the eventq of the specified channel immediately on this CPU 324/* Process the eventq of the specified channel immediately on this CPU
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 4105f9099c7c..f3226bbf9831 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -654,22 +654,23 @@ void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
654 * The NIC batches TX completion events; the message we receive is of 654 * The NIC batches TX completion events; the message we receive is of
655 * the form "complete all TX events up to this index". 655 * the form "complete all TX events up to this index".
656 */ 656 */
657static void 657static int
658efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) 658efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
659{ 659{
660 unsigned int tx_ev_desc_ptr; 660 unsigned int tx_ev_desc_ptr;
661 unsigned int tx_ev_q_label; 661 unsigned int tx_ev_q_label;
662 struct efx_tx_queue *tx_queue; 662 struct efx_tx_queue *tx_queue;
663 struct efx_nic *efx = channel->efx; 663 struct efx_nic *efx = channel->efx;
664 int tx_packets = 0;
664 665
665 if (likely(EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_COMP))) { 666 if (likely(EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_COMP))) {
666 /* Transmit completion */ 667 /* Transmit completion */
667 tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR); 668 tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
668 tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL); 669 tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
669 tx_queue = &efx->tx_queue[tx_ev_q_label]; 670 tx_queue = &efx->tx_queue[tx_ev_q_label];
670 channel->irq_mod_score += 671 tx_packets = ((tx_ev_desc_ptr - tx_queue->read_count) &
671 (tx_ev_desc_ptr - tx_queue->read_count) & 672 EFX_TXQ_MASK);
672 EFX_TXQ_MASK; 673 channel->irq_mod_score += tx_packets;
673 efx_xmit_done(tx_queue, tx_ev_desc_ptr); 674 efx_xmit_done(tx_queue, tx_ev_desc_ptr);
674 } else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) { 675 } else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
675 /* Rewrite the FIFO write pointer */ 676 /* Rewrite the FIFO write pointer */
@@ -689,6 +690,8 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
689 EFX_QWORD_FMT"\n", channel->channel, 690 EFX_QWORD_FMT"\n", channel->channel,
690 EFX_QWORD_VAL(*event)); 691 EFX_QWORD_VAL(*event));
691 } 692 }
693
694 return tx_packets;
692} 695}
693 696
694/* Detect errors included in the rx_evt_pkt_ok bit. */ 697/* Detect errors included in the rx_evt_pkt_ok bit. */
@@ -947,16 +950,17 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
947 } 950 }
948} 951}
949 952
950int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota) 953int efx_nic_process_eventq(struct efx_channel *channel, int budget)
951{ 954{
952 unsigned int read_ptr; 955 unsigned int read_ptr;
953 efx_qword_t event, *p_event; 956 efx_qword_t event, *p_event;
954 int ev_code; 957 int ev_code;
955 int rx_packets = 0; 958 int tx_packets = 0;
959 int spent = 0;
956 960
957 read_ptr = channel->eventq_read_ptr; 961 read_ptr = channel->eventq_read_ptr;
958 962
959 do { 963 for (;;) {
960 p_event = efx_event(channel, read_ptr); 964 p_event = efx_event(channel, read_ptr);
961 event = *p_event; 965 event = *p_event;
962 966
@@ -970,15 +974,23 @@ int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota)
970 /* Clear this event by marking it all ones */ 974 /* Clear this event by marking it all ones */
971 EFX_SET_QWORD(*p_event); 975 EFX_SET_QWORD(*p_event);
972 976
977 /* Increment read pointer */
978 read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
979
973 ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE); 980 ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
974 981
975 switch (ev_code) { 982 switch (ev_code) {
976 case FSE_AZ_EV_CODE_RX_EV: 983 case FSE_AZ_EV_CODE_RX_EV:
977 efx_handle_rx_event(channel, &event); 984 efx_handle_rx_event(channel, &event);
978 ++rx_packets; 985 if (++spent == budget)
986 goto out;
979 break; 987 break;
980 case FSE_AZ_EV_CODE_TX_EV: 988 case FSE_AZ_EV_CODE_TX_EV:
981 efx_handle_tx_event(channel, &event); 989 tx_packets += efx_handle_tx_event(channel, &event);
990 if (tx_packets >= EFX_TXQ_SIZE) {
991 spent = budget;
992 goto out;
993 }
982 break; 994 break;
983 case FSE_AZ_EV_CODE_DRV_GEN_EV: 995 case FSE_AZ_EV_CODE_DRV_GEN_EV:
984 channel->eventq_magic = EFX_QWORD_FIELD( 996 channel->eventq_magic = EFX_QWORD_FIELD(
@@ -1001,14 +1013,11 @@ int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota)
1001 " (data " EFX_QWORD_FMT ")\n", channel->channel, 1013 " (data " EFX_QWORD_FMT ")\n", channel->channel,
1002 ev_code, EFX_QWORD_VAL(event)); 1014 ev_code, EFX_QWORD_VAL(event));
1003 } 1015 }
1016 }
1004 1017
1005 /* Increment read pointer */ 1018out:
1006 read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
1007
1008 } while (rx_packets < rx_quota);
1009
1010 channel->eventq_read_ptr = read_ptr; 1019 channel->eventq_read_ptr = read_ptr;
1011 return rx_packets; 1020 return spent;
1012} 1021}
1013 1022
1014 1023