aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale/gianfar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.c')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c87
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index ef95c3ae53e6..b14d7904a075 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2920,7 +2920,7 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2920 struct gfar_priv_rx_q *rx_queue = NULL; 2920 struct gfar_priv_rx_q *rx_queue = NULL;
2921 int work_done = 0, work_done_per_q = 0; 2921 int work_done = 0, work_done_per_q = 0;
2922 int i, budget_per_q = 0; 2922 int i, budget_per_q = 0;
2923 int has_tx_work; 2923 int has_tx_work = 0;
2924 unsigned long rstat_rxf; 2924 unsigned long rstat_rxf;
2925 int num_act_queues; 2925 int num_act_queues;
2926 2926
@@ -2935,62 +2935,51 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2935 if (num_act_queues) 2935 if (num_act_queues)
2936 budget_per_q = budget/num_act_queues; 2936 budget_per_q = budget/num_act_queues;
2937 2937
2938 while (1) { 2938 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
2939 has_tx_work = 0; 2939 tx_queue = priv->tx_queue[i];
2940 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) { 2940 /* run Tx cleanup to completion */
2941 tx_queue = priv->tx_queue[i]; 2941 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
2942 /* run Tx cleanup to completion */ 2942 gfar_clean_tx_ring(tx_queue);
2943 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) { 2943 has_tx_work = 1;
2944 gfar_clean_tx_ring(tx_queue);
2945 has_tx_work = 1;
2946 }
2947 } 2944 }
2945 }
2948 2946
2949 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { 2947 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
2950 /* skip queue if not active */ 2948 /* skip queue if not active */
2951 if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i))) 2949 if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
2952 continue; 2950 continue;
2953
2954 rx_queue = priv->rx_queue[i];
2955 work_done_per_q =
2956 gfar_clean_rx_ring(rx_queue, budget_per_q);
2957 work_done += work_done_per_q;
2958
2959 /* finished processing this queue */
2960 if (work_done_per_q < budget_per_q) {
2961 /* clear active queue hw indication */
2962 gfar_write(&regs->rstat,
2963 RSTAT_CLEAR_RXF0 >> i);
2964 rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i);
2965 num_act_queues--;
2966
2967 if (!num_act_queues)
2968 break;
2969 /* recompute budget per Rx queue */
2970 budget_per_q =
2971 (budget - work_done) / num_act_queues;
2972 }
2973 }
2974 2951
2975 if (work_done >= budget) 2952 rx_queue = priv->rx_queue[i];
2976 break; 2953 work_done_per_q =
2954 gfar_clean_rx_ring(rx_queue, budget_per_q);
2955 work_done += work_done_per_q;
2956
2957 /* finished processing this queue */
2958 if (work_done_per_q < budget_per_q) {
2959 /* clear active queue hw indication */
2960 gfar_write(&regs->rstat,
2961 RSTAT_CLEAR_RXF0 >> i);
2962 num_act_queues--;
2963
2964 if (!num_act_queues)
2965 break;
2966 }
2967 }
2977 2968
2978 if (!num_act_queues && !has_tx_work) { 2969 if (!num_act_queues && !has_tx_work) {
2979 2970
2980 napi_complete(napi); 2971 napi_complete(napi);
2981 2972
2982 /* Clear the halt bit in RSTAT */ 2973 /* Clear the halt bit in RSTAT */
2983 gfar_write(&regs->rstat, gfargrp->rstat); 2974 gfar_write(&regs->rstat, gfargrp->rstat);
2984 2975
2985 gfar_write(&regs->imask, IMASK_DEFAULT); 2976 gfar_write(&regs->imask, IMASK_DEFAULT);
2986 2977
2987 /* If we are coalescing interrupts, update the timer 2978 /* If we are coalescing interrupts, update the timer
2988 * Otherwise, clear it 2979 * Otherwise, clear it
2989 */ 2980 */
2990 gfar_configure_coalescing(priv, gfargrp->rx_bit_map, 2981 gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
2991 gfargrp->tx_bit_map); 2982 gfargrp->tx_bit_map);
2992 break;
2993 }
2994 } 2983 }
2995 2984
2996 return work_done; 2985 return work_done;