diff options
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 18 | ||||
-rw-r--r-- | drivers/net/sfc/nic.c | 39 |
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 | */ |
228 | static int efx_process_channel(struct efx_channel *channel, int rx_quota) | 228 | static 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 | */ |
657 | static void | 657 | static int |
658 | efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) | 658 | efx_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 | ||
950 | int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota) | 953 | int 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 */ | 1018 | out: |
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 | ||