aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c28
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h4
2 files changed, 22 insertions, 10 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 1e555a70b821..3f07dbd01980 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2835,15 +2835,20 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2835 int work_done = 0, work_done_per_q = 0; 2835 int work_done = 0, work_done_per_q = 0;
2836 int i, budget_per_q; 2836 int i, budget_per_q;
2837 int has_tx_work; 2837 int has_tx_work;
2838 unsigned long serviced_queues = 0; 2838 unsigned long rstat_rxf;
2839 int num_queues = gfargrp->num_rx_queues; 2839 int num_act_queues;
2840 2840
2841 budget_per_q = budget/num_queues;
2842 /* Clear IEVENT, so interrupts aren't called again 2841 /* Clear IEVENT, so interrupts aren't called again
2843 * because of the packets that have already arrived 2842 * because of the packets that have already arrived
2844 */ 2843 */
2845 gfar_write(&regs->ievent, IEVENT_RTX_MASK); 2844 gfar_write(&regs->ievent, IEVENT_RTX_MASK);
2846 2845
2846 rstat_rxf = gfar_read(&regs->rstat) & RSTAT_RXF_MASK;
2847
2848 num_act_queues = bitmap_weight(&rstat_rxf, MAX_RX_QS);
2849 if (num_act_queues)
2850 budget_per_q = budget/num_act_queues;
2851
2847 while (1) { 2852 while (1) {
2848 has_tx_work = 0; 2853 has_tx_work = 0;
2849 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) { 2854 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
@@ -2856,7 +2861,8 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2856 } 2861 }
2857 2862
2858 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { 2863 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
2859 if (test_bit(i, &serviced_queues)) 2864 /* skip queue if not active */
2865 if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
2860 continue; 2866 continue;
2861 2867
2862 rx_queue = priv->rx_queue[i]; 2868 rx_queue = priv->rx_queue[i];
@@ -2866,20 +2872,24 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2866 2872
2867 /* finished processing this queue */ 2873 /* finished processing this queue */
2868 if (work_done_per_q < budget_per_q) { 2874 if (work_done_per_q < budget_per_q) {
2869 set_bit(i, &serviced_queues); 2875 /* clear active queue hw indication */
2870 num_queues--; 2876 gfar_write(&regs->rstat,
2871 if (!num_queues) 2877 RSTAT_CLEAR_RXF0 >> i);
2878 rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i);
2879 num_act_queues--;
2880
2881 if (!num_act_queues)
2872 break; 2882 break;
2873 /* recompute budget per Rx queue */ 2883 /* recompute budget per Rx queue */
2874 budget_per_q = 2884 budget_per_q =
2875 (budget - work_done) / num_queues; 2885 (budget - work_done) / num_act_queues;
2876 } 2886 }
2877 } 2887 }
2878 2888
2879 if (work_done >= budget) 2889 if (work_done >= budget)
2880 break; 2890 break;
2881 2891
2882 if (!num_queues && !has_tx_work) { 2892 if (!num_act_queues && !has_tx_work) {
2883 2893
2884 napi_complete(napi); 2894 napi_complete(napi);
2885 2895
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 63a28d294e20..b1d0c1c77139 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -291,7 +291,9 @@ extern const char gfar_driver_version[];
291#define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK) 291#define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK)
292 292
293 293
294#define RSTAT_CLEAR_RHALT 0x00800000 294#define RSTAT_CLEAR_RHALT 0x00800000
295#define RSTAT_CLEAR_RXF0 0x00000080
296#define RSTAT_RXF_MASK 0x000000ff
295 297
296#define TCTRL_IPCSEN 0x00004000 298#define TCTRL_IPCSEN 0x00004000
297#define TCTRL_TUCSEN 0x00002000 299#define TCTRL_TUCSEN 0x00002000