mpc85xx: Fix NAPI poll mechanism in GIANFAR ethernet driver
[openwrt.git] / target / linux / mpc85xx / patches-3.10 / 200-fix_gianfar_napi_poll.patch
1 --- a/drivers/net/ethernet/freescale/gianfar.c
2 +++ b/drivers/net/ethernet/freescale/gianfar.c
3 @@ -2835,7 +2835,7 @@ static int gfar_poll(struct napi_struct 
4         struct gfar_priv_rx_q *rx_queue = NULL;
5         int work_done = 0, work_done_per_q = 0;
6         int i, budget_per_q = 0;
7 -       int has_tx_work;
8 +       int has_tx_work = 0;
9         unsigned long rstat_rxf;
10         int num_act_queues;
11  
12 @@ -2850,62 +2850,48 @@ static int gfar_poll(struct napi_struct 
13         if (num_act_queues)
14                 budget_per_q = budget/num_act_queues;
15  
16 -       while (1) {
17 -               has_tx_work = 0;
18 -               for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
19 -                       tx_queue = priv->tx_queue[i];
20 -                       /* run Tx cleanup to completion */
21 -                       if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
22 -                               gfar_clean_tx_ring(tx_queue);
23 -                               has_tx_work = 1;
24 -                       }
25 -               }
26 -
27 -               for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
28 -                       /* skip queue if not active */
29 -                       if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
30 -                               continue;
31 -
32 -                       rx_queue = priv->rx_queue[i];
33 -                       work_done_per_q =
34 -                               gfar_clean_rx_ring(rx_queue, budget_per_q);
35 -                       work_done += work_done_per_q;
36 -
37 -                       /* finished processing this queue */
38 -                       if (work_done_per_q < budget_per_q) {
39 -                               /* clear active queue hw indication */
40 -                               gfar_write(&regs->rstat,
41 -                                          RSTAT_CLEAR_RXF0 >> i);
42 -                               rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i);
43 -                               num_act_queues--;
44 -
45 -                               if (!num_act_queues)
46 -                                       break;
47 -                               /* recompute budget per Rx queue */
48 -                               budget_per_q =
49 -                                       (budget - work_done) / num_act_queues;
50 -                       }
51 +       for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
52 +               tx_queue = priv->tx_queue[i];
53 +               /* run Tx cleanup to completion */
54 +               if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
55 +                       gfar_clean_tx_ring(tx_queue);
56 +                       has_tx_work = 1;
57                 }
58 +       }
59  
60 -               if (work_done >= budget)
61 -                       break;
62 +       for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
63 +               /* skip queue if not active */
64 +               if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
65 +                       continue;
66 +
67 +               rx_queue = priv->rx_queue[i];
68 +               work_done_per_q = gfar_clean_rx_ring(rx_queue, budget_per_q);
69 +               work_done += work_done_per_q;
70 +
71 +               /* finished processing this queue */
72 +               if (work_done_per_q < budget_per_q) {
73 +                       /* clear active queue hw indication */
74 +                       gfar_write(&regs->rstat, RSTAT_CLEAR_RXF0 >> i);
75 +                       num_act_queues--;
76  
77 -               if (!num_act_queues && !has_tx_work) {
78 +                       if (!num_act_queues)
79 +                               break;
80 +               }
81 +       }
82  
83 -                       napi_complete(napi);
84 +       if (!num_act_queues && !has_tx_work) {
85 +               napi_complete(napi);
86  
87 -                       /* Clear the halt bit in RSTAT */
88 -                       gfar_write(&regs->rstat, gfargrp->rstat);
89 +               /* Clear the halt bit in RSTAT */
90 +               gfar_write(&regs->rstat, gfargrp->rstat);
91  
92 -                       gfar_write(&regs->imask, IMASK_DEFAULT);
93 +               gfar_write(&regs->imask, IMASK_DEFAULT);
94  
95 -                       /* If we are coalescing interrupts, update the timer
96 -                        * Otherwise, clear it
97 -                        */
98 -                       gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
99 -                                                 gfargrp->tx_bit_map);
100 -                       break;
101 -               }
102 +               /* If we are coalescing interrupts, update the timer
103 +                * Otherwise, clear it
104 +                */
105 +               gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
106 +                                         gfargrp->tx_bit_map);
107         }
108  
109         return work_done;