kernel: update 3.10 to 3.10.21
[openwrt/svn-archive/archive.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;