diff options
Diffstat (limited to 'drivers/net')
| -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 |
