diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.c')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 82 |
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); | |||
132 | static void gfar_netpoll(struct net_device *dev); | 132 | static void gfar_netpoll(struct net_device *dev); |
133 | #endif | 133 | #endif |
134 | int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); | 134 | int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); |
135 | static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); | 135 | static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); |
136 | static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, | 136 | static 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); |
138 | void gfar_halt(struct net_device *dev); | 138 | void 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 */ |
2471 | static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) | 2471 | static 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 | ||
2577 | static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp) | 2575 | static 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(®s->ievent, IEVENT_RTX_MASK); | 2845 | gfar_write(®s->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(®s->rstat, gfargrp->rstat); | ||
2882 | 2885 | ||
2883 | gfar_write(®s->imask, IMASK_DEFAULT); | 2886 | /* Clear the halt bit in RSTAT */ |
2887 | gfar_write(®s->rstat, gfargrp->rstat); | ||
2884 | 2888 | ||
2885 | /* If we are coalescing interrupts, update the timer | 2889 | gfar_write(®s->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 |