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.c82
1 files changed, 45 insertions, 37 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 1b468a82a68f..1e555a70b821 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -132,7 +132,7 @@ static int gfar_poll(struct napi_struct *napi, int budget);
132static void gfar_netpoll(struct net_device *dev); 132static void gfar_netpoll(struct net_device *dev);
133#endif 133#endif
134int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); 134int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
135static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); 135static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
136static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, 136static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
137 int amount_pull, struct napi_struct *napi); 137 int amount_pull, struct napi_struct *napi);
138void gfar_halt(struct net_device *dev); 138void gfar_halt(struct net_device *dev);
@@ -2468,7 +2468,7 @@ static void gfar_align_skb(struct sk_buff *skb)
2468} 2468}
2469 2469
2470/* Interrupt Handler for Transmit complete */ 2470/* Interrupt Handler for Transmit complete */
2471static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) 2471static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2472{ 2472{
2473 struct net_device *dev = tx_queue->dev; 2473 struct net_device *dev = tx_queue->dev;
2474 struct netdev_queue *txq; 2474 struct netdev_queue *txq;
@@ -2570,8 +2570,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2570 tx_queue->dirty_tx = bdp; 2570 tx_queue->dirty_tx = bdp;
2571 2571
2572 netdev_tx_completed_queue(txq, howmany, bytes_sent); 2572 netdev_tx_completed_queue(txq, howmany, bytes_sent);
2573
2574 return howmany;
2575} 2573}
2576 2574
2577static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp) 2575static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp)
@@ -2834,62 +2832,72 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2834 struct gfar __iomem *regs = gfargrp->regs; 2832 struct gfar __iomem *regs = gfargrp->regs;
2835 struct gfar_priv_tx_q *tx_queue = NULL; 2833 struct gfar_priv_tx_q *tx_queue = NULL;
2836 struct gfar_priv_rx_q *rx_queue = NULL; 2834 struct gfar_priv_rx_q *rx_queue = NULL;
2837 int rx_cleaned = 0, budget_per_queue = 0, rx_cleaned_per_queue = 0; 2835 int work_done = 0, work_done_per_q = 0;
2838 int tx_cleaned = 0, i, left_over_budget = budget; 2836 int i, budget_per_q;
2837 int has_tx_work;
2839 unsigned long serviced_queues = 0; 2838 unsigned long serviced_queues = 0;
2840 int num_queues = 0; 2839 int num_queues = gfargrp->num_rx_queues;
2841
2842 num_queues = gfargrp->num_rx_queues;
2843 budget_per_queue = budget/num_queues;
2844 2840
2841 budget_per_q = budget/num_queues;
2845 /* Clear IEVENT, so interrupts aren't called again 2842 /* Clear IEVENT, so interrupts aren't called again
2846 * because of the packets that have already arrived 2843 * because of the packets that have already arrived
2847 */ 2844 */
2848 gfar_write(&regs->ievent, IEVENT_RTX_MASK); 2845 gfar_write(&regs->ievent, IEVENT_RTX_MASK);
2849 2846
2850 while (num_queues && left_over_budget) { 2847 while (1) {
2851 budget_per_queue = left_over_budget/num_queues; 2848 has_tx_work = 0;
2852 left_over_budget = 0; 2849 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
2850 tx_queue = priv->tx_queue[i];
2851 /* run Tx cleanup to completion */
2852 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
2853 gfar_clean_tx_ring(tx_queue);
2854 has_tx_work = 1;
2855 }
2856 }
2853 2857
2854 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { 2858 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
2855 if (test_bit(i, &serviced_queues)) 2859 if (test_bit(i, &serviced_queues))
2856 continue; 2860 continue;
2861
2857 rx_queue = priv->rx_queue[i]; 2862 rx_queue = priv->rx_queue[i];
2858 tx_queue = priv->tx_queue[rx_queue->qindex]; 2863 work_done_per_q =
2859 2864 gfar_clean_rx_ring(rx_queue, budget_per_q);
2860 tx_cleaned += gfar_clean_tx_ring(tx_queue); 2865 work_done += work_done_per_q;
2861 rx_cleaned_per_queue = 2866
2862 gfar_clean_rx_ring(rx_queue, budget_per_queue); 2867 /* finished processing this queue */
2863 rx_cleaned += rx_cleaned_per_queue; 2868 if (work_done_per_q < budget_per_q) {
2864 if (rx_cleaned_per_queue < budget_per_queue) {
2865 left_over_budget = left_over_budget +
2866 (budget_per_queue -
2867 rx_cleaned_per_queue);
2868 set_bit(i, &serviced_queues); 2869 set_bit(i, &serviced_queues);
2869 num_queues--; 2870 num_queues--;
2871 if (!num_queues)
2872 break;
2873 /* recompute budget per Rx queue */
2874 budget_per_q =
2875 (budget - work_done) / num_queues;
2870 } 2876 }
2871 } 2877 }
2872 }
2873 2878
2874 if (tx_cleaned) 2879 if (work_done >= budget)
2875 return budget; 2880 break;
2876 2881
2877 if (rx_cleaned < budget) { 2882 if (!num_queues && !has_tx_work) {
2878 napi_complete(napi);
2879 2883
2880 /* Clear the halt bit in RSTAT */ 2884 napi_complete(napi);
2881 gfar_write(&regs->rstat, gfargrp->rstat);
2882 2885
2883 gfar_write(&regs->imask, IMASK_DEFAULT); 2886 /* Clear the halt bit in RSTAT */
2887 gfar_write(&regs->rstat, gfargrp->rstat);
2884 2888
2885 /* If we are coalescing interrupts, update the timer 2889 gfar_write(&regs->imask, IMASK_DEFAULT);
2886 * Otherwise, clear it 2890
2887 */ 2891 /* If we are coalescing interrupts, update the timer
2888 gfar_configure_coalescing(priv, gfargrp->rx_bit_map, 2892 * Otherwise, clear it
2889 gfargrp->tx_bit_map); 2893 */
2894 gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
2895 gfargrp->tx_bit_map);
2896 break;
2897 }
2890 } 2898 }
2891 2899
2892 return rx_cleaned; 2900 return work_done;
2893} 2901}
2894 2902
2895#ifdef CONFIG_NET_POLL_CONTROLLER 2903#ifdef CONFIG_NET_POLL_CONTROLLER