aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2013-03-19 03:40:03 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-20 13:21:52 -0400
commit6be5ed3fef568ad79f9519db4a336c725a089d51 (patch)
treeac6f3c7e6780dcbacbd6d65d3ab43460d87d0e3a /drivers/net/ethernet/freescale
parentc233cf4074e50933edd5e82c3c5826923f0c1b10 (diff)
gianfar: Poll only active Rx queues
Split the napi budget fairly among the active queues only, instead of dividing it by the total number of Rx queues assigned to the given interrupt group. Use the h/w indication field RXFi in rstat (receive status register) to identify the active rx queues from the current interrupt group (i.e. receive event occured on ring i, if ring i is part of the current interrupt group). This indication field in rstat, RXFi i=0..7, allows us to find out on which queues of the same interrupt group do we have incomming traffic once we entered the polling routine for the given interrupt group. After servicing the ring i, the corresponding bit RXFi will be written with 1 to clear the active queue indication for that ring. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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