aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2014-03-07 07:42:45 -0500
committerDavid S. Miller <davem@davemloft.net>2014-03-10 13:17:22 -0400
commitaeb12c5ef7cb08d879af22fc0a56cab9e70689ea (patch)
treeba657f19e9c0a8c3658bb780dea4f52bcf66caeb /drivers/net
parentbe14cc98e9fd5416cc8f86799913fd3c52dc720e (diff)
gianfar: Separate out the Tx interrupt handling (Tx NAPI)
There are some concurrency issues on devices w/ 2 CPUs related to the handling of Rx and Tx interrupts. eTSEC has separate interrupt lines for Rx and Tx but a single imask register to mask these interrupts and a single NAPI instance to handle both Rx and Tx work. As a result, the Rx and Tx ISRs are identical, both are invoking gfar_schedule_cleanup(), however both handlers can be entered at the same time when the Rx and Tx interrupts are taken by different CPUs. In this case spurrious interrupts (SPU) show up (in /proc/interrupts) indicating a concurrency issue. Also, Tx overruns followed by Tx timeout have been observed under heavy Tx traffic load. To address these issues, the schedule cleanup ISR part has been changed to handle the Rx and Tx interrupts independently. The patch adds a separate NAPI poll routine for Tx cleanup to be triggerred independently by the Tx confirmation interrupts only. Existing poll functions are modified to handle only the Rx path processing. The Tx poll routine does not need a budget, since Tx processing doesn't consume NAPI budget, and hence it is registered with minimum NAPI weight. NAPI scheduling does not require locking since there are different NAPI instances between the Rx and Tx confirmation paths now. So, the patch fixes the occurence of spurrious Rx/Tx interrupts. Tx overruns also occur less frequently now. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c218
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h11
2 files changed, 160 insertions, 69 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index c5b9320f7629..1aa2d55aa014 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -128,8 +128,10 @@ static void free_skb_resources(struct gfar_private *priv);
128static void gfar_set_multi(struct net_device *dev); 128static void gfar_set_multi(struct net_device *dev);
129static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); 129static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
130static void gfar_configure_serdes(struct net_device *dev); 130static void gfar_configure_serdes(struct net_device *dev);
131static int gfar_poll(struct napi_struct *napi, int budget); 131static int gfar_poll_rx(struct napi_struct *napi, int budget);
132static int gfar_poll_sq(struct napi_struct *napi, int budget); 132static int gfar_poll_tx(struct napi_struct *napi, int budget);
133static int gfar_poll_rx_sq(struct napi_struct *napi, int budget);
134static int gfar_poll_tx_sq(struct napi_struct *napi, int budget);
133#ifdef CONFIG_NET_POLL_CONTROLLER 135#ifdef CONFIG_NET_POLL_CONTROLLER
134static void gfar_netpoll(struct net_device *dev); 136static void gfar_netpoll(struct net_device *dev);
135#endif 137#endif
@@ -614,16 +616,20 @@ static void disable_napi(struct gfar_private *priv)
614{ 616{
615 int i; 617 int i;
616 618
617 for (i = 0; i < priv->num_grps; i++) 619 for (i = 0; i < priv->num_grps; i++) {
618 napi_disable(&priv->gfargrp[i].napi); 620 napi_disable(&priv->gfargrp[i].napi_rx);
621 napi_disable(&priv->gfargrp[i].napi_tx);
622 }
619} 623}
620 624
621static void enable_napi(struct gfar_private *priv) 625static void enable_napi(struct gfar_private *priv)
622{ 626{
623 int i; 627 int i;
624 628
625 for (i = 0; i < priv->num_grps; i++) 629 for (i = 0; i < priv->num_grps; i++) {
626 napi_enable(&priv->gfargrp[i].napi); 630 napi_enable(&priv->gfargrp[i].napi_rx);
631 napi_enable(&priv->gfargrp[i].napi_tx);
632 }
627} 633}
628 634
629static int gfar_parse_group(struct device_node *np, 635static int gfar_parse_group(struct device_node *np,
@@ -1257,13 +1263,19 @@ static int gfar_probe(struct platform_device *ofdev)
1257 dev->ethtool_ops = &gfar_ethtool_ops; 1263 dev->ethtool_ops = &gfar_ethtool_ops;
1258 1264
1259 /* Register for napi ...We are registering NAPI for each grp */ 1265 /* Register for napi ...We are registering NAPI for each grp */
1260 if (priv->mode == SQ_SG_MODE) 1266 if (priv->mode == SQ_SG_MODE) {
1261 netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq, 1267 netif_napi_add(dev, &priv->gfargrp[0].napi_rx, gfar_poll_rx_sq,
1262 GFAR_DEV_WEIGHT); 1268 GFAR_DEV_WEIGHT);
1263 else 1269 netif_napi_add(dev, &priv->gfargrp[0].napi_tx, gfar_poll_tx_sq,
1264 for (i = 0; i < priv->num_grps; i++) 1270 2);
1265 netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, 1271 } else {
1266 GFAR_DEV_WEIGHT); 1272 for (i = 0; i < priv->num_grps; i++) {
1273 netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
1274 gfar_poll_rx, GFAR_DEV_WEIGHT);
1275 netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
1276 gfar_poll_tx, 2);
1277 }
1278 }
1267 1279
1268 if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { 1280 if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
1269 dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | 1281 dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
@@ -2538,31 +2550,6 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
2538 netdev_tx_completed_queue(txq, howmany, bytes_sent); 2550 netdev_tx_completed_queue(txq, howmany, bytes_sent);
2539} 2551}
2540 2552
2541static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp)
2542{
2543 unsigned long flags;
2544
2545 spin_lock_irqsave(&gfargrp->grplock, flags);
2546 if (napi_schedule_prep(&gfargrp->napi)) {
2547 gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED);
2548 __napi_schedule(&gfargrp->napi);
2549 } else {
2550 /* Clear IEVENT, so interrupts aren't called again
2551 * because of the packets that have already arrived.
2552 */
2553 gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK);
2554 }
2555 spin_unlock_irqrestore(&gfargrp->grplock, flags);
2556
2557}
2558
2559/* Interrupt Handler for Transmit complete */
2560static irqreturn_t gfar_transmit(int irq, void *grp_id)
2561{
2562 gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
2563 return IRQ_HANDLED;
2564}
2565
2566static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, 2553static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
2567 struct sk_buff *skb) 2554 struct sk_buff *skb)
2568{ 2555{
@@ -2633,7 +2620,48 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
2633 2620
2634irqreturn_t gfar_receive(int irq, void *grp_id) 2621irqreturn_t gfar_receive(int irq, void *grp_id)
2635{ 2622{
2636 gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id); 2623 struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
2624 unsigned long flags;
2625 u32 imask;
2626
2627 if (likely(napi_schedule_prep(&grp->napi_rx))) {
2628 spin_lock_irqsave(&grp->grplock, flags);
2629 imask = gfar_read(&grp->regs->imask);
2630 imask &= IMASK_RX_DISABLED;
2631 gfar_write(&grp->regs->imask, imask);
2632 spin_unlock_irqrestore(&grp->grplock, flags);
2633 __napi_schedule(&grp->napi_rx);
2634 } else {
2635 /* Clear IEVENT, so interrupts aren't called again
2636 * because of the packets that have already arrived.
2637 */
2638 gfar_write(&grp->regs->ievent, IEVENT_RX_MASK);
2639 }
2640
2641 return IRQ_HANDLED;
2642}
2643
2644/* Interrupt Handler for Transmit complete */
2645static irqreturn_t gfar_transmit(int irq, void *grp_id)
2646{
2647 struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
2648 unsigned long flags;
2649 u32 imask;
2650
2651 if (likely(napi_schedule_prep(&grp->napi_tx))) {
2652 spin_lock_irqsave(&grp->grplock, flags);
2653 imask = gfar_read(&grp->regs->imask);
2654 imask &= IMASK_TX_DISABLED;
2655 gfar_write(&grp->regs->imask, imask);
2656 spin_unlock_irqrestore(&grp->grplock, flags);
2657 __napi_schedule(&grp->napi_tx);
2658 } else {
2659 /* Clear IEVENT, so interrupts aren't called again
2660 * because of the packets that have already arrived.
2661 */
2662 gfar_write(&grp->regs->ievent, IEVENT_TX_MASK);
2663 }
2664
2637 return IRQ_HANDLED; 2665 return IRQ_HANDLED;
2638} 2666}
2639 2667
@@ -2757,7 +2785,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
2757 rx_queue->stats.rx_bytes += pkt_len; 2785 rx_queue->stats.rx_bytes += pkt_len;
2758 skb_record_rx_queue(skb, rx_queue->qindex); 2786 skb_record_rx_queue(skb, rx_queue->qindex);
2759 gfar_process_frame(dev, skb, amount_pull, 2787 gfar_process_frame(dev, skb, amount_pull,
2760 &rx_queue->grp->napi); 2788 &rx_queue->grp->napi_rx);
2761 2789
2762 } else { 2790 } else {
2763 netif_warn(priv, rx_err, dev, "Missing skb!\n"); 2791 netif_warn(priv, rx_err, dev, "Missing skb!\n");
@@ -2786,55 +2814,81 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
2786 return howmany; 2814 return howmany;
2787} 2815}
2788 2816
2789static int gfar_poll_sq(struct napi_struct *napi, int budget) 2817static int gfar_poll_rx_sq(struct napi_struct *napi, int budget)
2790{ 2818{
2791 struct gfar_priv_grp *gfargrp = 2819 struct gfar_priv_grp *gfargrp =
2792 container_of(napi, struct gfar_priv_grp, napi); 2820 container_of(napi, struct gfar_priv_grp, napi_rx);
2793 struct gfar __iomem *regs = gfargrp->regs; 2821 struct gfar __iomem *regs = gfargrp->regs;
2794 struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0];
2795 struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0]; 2822 struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0];
2796 int work_done = 0; 2823 int work_done = 0;
2797 2824
2798 /* Clear IEVENT, so interrupts aren't called again 2825 /* Clear IEVENT, so interrupts aren't called again
2799 * because of the packets that have already arrived 2826 * because of the packets that have already arrived
2800 */ 2827 */
2801 gfar_write(&regs->ievent, IEVENT_RTX_MASK); 2828 gfar_write(&regs->ievent, IEVENT_RX_MASK);
2802
2803 /* run Tx cleanup to completion */
2804 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
2805 gfar_clean_tx_ring(tx_queue);
2806 2829
2807 work_done = gfar_clean_rx_ring(rx_queue, budget); 2830 work_done = gfar_clean_rx_ring(rx_queue, budget);
2808 2831
2809 if (work_done < budget) { 2832 if (work_done < budget) {
2833 u32 imask;
2810 napi_complete(napi); 2834 napi_complete(napi);
2811 /* Clear the halt bit in RSTAT */ 2835 /* Clear the halt bit in RSTAT */
2812 gfar_write(&regs->rstat, gfargrp->rstat); 2836 gfar_write(&regs->rstat, gfargrp->rstat);
2813 2837
2814 gfar_write(&regs->imask, IMASK_DEFAULT); 2838 spin_lock_irq(&gfargrp->grplock);
2839 imask = gfar_read(&regs->imask);
2840 imask |= IMASK_RX_DEFAULT;
2841 gfar_write(&regs->imask, imask);
2842 spin_unlock_irq(&gfargrp->grplock);
2815 } 2843 }
2816 2844
2817 return work_done; 2845 return work_done;
2818} 2846}
2819 2847
2820static int gfar_poll(struct napi_struct *napi, int budget) 2848static int gfar_poll_tx_sq(struct napi_struct *napi, int budget)
2821{ 2849{
2822 struct gfar_priv_grp *gfargrp = 2850 struct gfar_priv_grp *gfargrp =
2823 container_of(napi, struct gfar_priv_grp, napi); 2851 container_of(napi, struct gfar_priv_grp, napi_tx);
2852 struct gfar __iomem *regs = gfargrp->regs;
2853 struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0];
2854 u32 imask;
2855
2856 /* Clear IEVENT, so interrupts aren't called again
2857 * because of the packets that have already arrived
2858 */
2859 gfar_write(&regs->ievent, IEVENT_TX_MASK);
2860
2861 /* run Tx cleanup to completion */
2862 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
2863 gfar_clean_tx_ring(tx_queue);
2864
2865 napi_complete(napi);
2866
2867 spin_lock_irq(&gfargrp->grplock);
2868 imask = gfar_read(&regs->imask);
2869 imask |= IMASK_TX_DEFAULT;
2870 gfar_write(&regs->imask, imask);
2871 spin_unlock_irq(&gfargrp->grplock);
2872
2873 return 0;
2874}
2875
2876static int gfar_poll_rx(struct napi_struct *napi, int budget)
2877{
2878 struct gfar_priv_grp *gfargrp =
2879 container_of(napi, struct gfar_priv_grp, napi_rx);
2824 struct gfar_private *priv = gfargrp->priv; 2880 struct gfar_private *priv = gfargrp->priv;
2825 struct gfar __iomem *regs = gfargrp->regs; 2881 struct gfar __iomem *regs = gfargrp->regs;
2826 struct gfar_priv_tx_q *tx_queue = NULL;
2827 struct gfar_priv_rx_q *rx_queue = NULL; 2882 struct gfar_priv_rx_q *rx_queue = NULL;
2828 int work_done = 0, work_done_per_q = 0; 2883 int work_done = 0, work_done_per_q = 0;
2829 int i, budget_per_q = 0; 2884 int i, budget_per_q = 0;
2830 int has_tx_work = 0;
2831 unsigned long rstat_rxf; 2885 unsigned long rstat_rxf;
2832 int num_act_queues; 2886 int num_act_queues;
2833 2887
2834 /* Clear IEVENT, so interrupts aren't called again 2888 /* Clear IEVENT, so interrupts aren't called again
2835 * because of the packets that have already arrived 2889 * because of the packets that have already arrived
2836 */ 2890 */
2837 gfar_write(&regs->ievent, IEVENT_RTX_MASK); 2891 gfar_write(&regs->ievent, IEVENT_RX_MASK);
2838 2892
2839 rstat_rxf = gfar_read(&regs->rstat) & RSTAT_RXF_MASK; 2893 rstat_rxf = gfar_read(&regs->rstat) & RSTAT_RXF_MASK;
2840 2894
@@ -2842,15 +2896,6 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2842 if (num_act_queues) 2896 if (num_act_queues)
2843 budget_per_q = budget/num_act_queues; 2897 budget_per_q = budget/num_act_queues;
2844 2898
2845 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
2846 tx_queue = priv->tx_queue[i];
2847 /* run Tx cleanup to completion */
2848 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
2849 gfar_clean_tx_ring(tx_queue);
2850 has_tx_work = 1;
2851 }
2852 }
2853
2854 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { 2899 for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
2855 /* skip queue if not active */ 2900 /* skip queue if not active */
2856 if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i))) 2901 if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
@@ -2873,19 +2918,62 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2873 } 2918 }
2874 } 2919 }
2875 2920
2876 if (!num_act_queues && !has_tx_work) { 2921 if (!num_act_queues) {
2877 2922 u32 imask;
2878 napi_complete(napi); 2923 napi_complete(napi);
2879 2924
2880 /* Clear the halt bit in RSTAT */ 2925 /* Clear the halt bit in RSTAT */
2881 gfar_write(&regs->rstat, gfargrp->rstat); 2926 gfar_write(&regs->rstat, gfargrp->rstat);
2882 2927
2883 gfar_write(&regs->imask, IMASK_DEFAULT); 2928 spin_lock_irq(&gfargrp->grplock);
2929 imask = gfar_read(&regs->imask);
2930 imask |= IMASK_RX_DEFAULT;
2931 gfar_write(&regs->imask, imask);
2932 spin_unlock_irq(&gfargrp->grplock);
2884 } 2933 }
2885 2934
2886 return work_done; 2935 return work_done;
2887} 2936}
2888 2937
2938static int gfar_poll_tx(struct napi_struct *napi, int budget)
2939{
2940 struct gfar_priv_grp *gfargrp =
2941 container_of(napi, struct gfar_priv_grp, napi_tx);
2942 struct gfar_private *priv = gfargrp->priv;
2943 struct gfar __iomem *regs = gfargrp->regs;
2944 struct gfar_priv_tx_q *tx_queue = NULL;
2945 int has_tx_work = 0;
2946 int i;
2947
2948 /* Clear IEVENT, so interrupts aren't called again
2949 * because of the packets that have already arrived
2950 */
2951 gfar_write(&regs->ievent, IEVENT_TX_MASK);
2952
2953 for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
2954 tx_queue = priv->tx_queue[i];
2955 /* run Tx cleanup to completion */
2956 if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
2957 gfar_clean_tx_ring(tx_queue);
2958 has_tx_work = 1;
2959 }
2960 }
2961
2962 if (!has_tx_work) {
2963 u32 imask;
2964 napi_complete(napi);
2965
2966 spin_lock_irq(&gfargrp->grplock);
2967 imask = gfar_read(&regs->imask);
2968 imask |= IMASK_TX_DEFAULT;
2969 gfar_write(&regs->imask, imask);
2970 spin_unlock_irq(&gfargrp->grplock);
2971 }
2972
2973 return 0;
2974}
2975
2976
2889#ifdef CONFIG_NET_POLL_CONTROLLER 2977#ifdef CONFIG_NET_POLL_CONTROLLER
2890/* Polling 'interrupt' - used by things like netconsole to send skbs 2978/* Polling 'interrupt' - used by things like netconsole to send skbs
2891 * without having to re-enable interrupts. It's not called while 2979 * without having to re-enable interrupts. It's not called while
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 1e16216d4150..1aeb34e1efa5 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -377,8 +377,11 @@ extern const char gfar_driver_version[];
377 IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \ 377 IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
378 IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ 378 IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
379 | IMASK_PERR) 379 | IMASK_PERR)
380#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \ 380#define IMASK_RX_DEFAULT (IMASK_RXFEN0 | IMASK_BSY)
381 & IMASK_DEFAULT) 381#define IMASK_TX_DEFAULT (IMASK_TXFEN | IMASK_TXBEN)
382
383#define IMASK_RX_DISABLED ((~(IMASK_RX_DEFAULT)) & IMASK_DEFAULT)
384#define IMASK_TX_DISABLED ((~(IMASK_TX_DEFAULT)) & IMASK_DEFAULT)
382 385
383/* Fifo management */ 386/* Fifo management */
384#define FIFO_TX_THR_MASK 0x01ff 387#define FIFO_TX_THR_MASK 0x01ff
@@ -1014,13 +1017,13 @@ struct gfar_irqinfo {
1014 1017
1015struct gfar_priv_grp { 1018struct gfar_priv_grp {
1016 spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES))); 1019 spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES)));
1017 struct napi_struct napi; 1020 struct napi_struct napi_rx;
1021 struct napi_struct napi_tx;
1018 struct gfar_private *priv; 1022 struct gfar_private *priv;
1019 struct gfar __iomem *regs; 1023 struct gfar __iomem *regs;
1020 unsigned int rstat; 1024 unsigned int rstat;
1021 unsigned long num_rx_queues; 1025 unsigned long num_rx_queues;
1022 unsigned long rx_bit_map; 1026 unsigned long rx_bit_map;
1023 /* cacheline 3 */
1024 unsigned int tstat; 1027 unsigned int tstat;
1025 unsigned long num_tx_queues; 1028 unsigned long num_tx_queues;
1026 unsigned long tx_bit_map; 1029 unsigned long tx_bit_map;