This one adds an option to turn of napi and process rx directly in mscan isr. As
for mpc52xx this feature can be turned on by setting a rx-irq property int the
device tree, e.g:
c...@980 {
    compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
    interrupts = <2 18 0>;
    rx-irq;
    reg = <0x980 0x80>;
};
Default is the polling rx.

Signed-off-by: Luotao Fu <l...@pengutronix.de>
---
 kernel/2.6/drivers/net/can/mscan/mpc52xx_can.c |   18 +++-
 kernel/2.6/drivers/net/can/mscan/mscan.c       |  110 +++++++++++++++---------
 kernel/2.6/drivers/net/can/mscan/mscan.h       |    5 +-
 3 files changed, 88 insertions(+), 45 deletions(-)

diff --git a/kernel/2.6/drivers/net/can/mscan/mpc52xx_can.c 
b/kernel/2.6/drivers/net/can/mscan/mpc52xx_can.c
index 6a3d608..98fca19 100644
--- a/kernel/2.6/drivers/net/can/mscan/mpc52xx_can.c
+++ b/kernel/2.6/drivers/net/can/mscan/mpc52xx_can.c
@@ -340,7 +340,7 @@ static int __devinit mpc52xx_can_probe(struct of_device 
*ofdev,
        struct can_priv *priv;
        struct resource res;
        void __iomem *base;
-       int err, irq, res_size, clock_src;
+       int err, irq, res_size, clock_src, rx_mode;
 
        err = of_address_to_resource(np, 0, &res);
        if (err) {
@@ -371,7 +371,13 @@ static int __devinit mpc52xx_can_probe(struct of_device 
*ofdev,
                goto exit_unmap_mem;
        }
 
-       dev = alloc_mscandev();
+       if (of_get_property(np, "rx-irq", NULL))
+               rx_mode = RX_IRQ;
+       else
+               rx_mode = RX_POLL;
+
+       dev = alloc_mscandev(rx_mode);
+
        if (!dev) {
                err = -ENOMEM;
                goto exit_dispose_irq;
@@ -411,9 +417,11 @@ static int __devinit mpc52xx_can_probe(struct of_device 
*ofdev,
 
        dev_set_drvdata(&ofdev->dev, dev);
 
-       dev_info(&ofdev->dev, "MSCAN at 0x%lx, irq %d, clock %d Hz\n",
-                dev->base_addr, dev->irq, priv->clock.freq);
-
+       dev_info(&ofdev->dev, "MSCAN at 0x%lx, irq %d,"
+                " clock %d Hz, rx_mode: %s\n",
+                dev->base_addr, dev->irq, priv->clock.freq, 
+                rx_mode == RX_IRQ ? "irq" : "polling");
+ 
        return 0;
 
 exit_free_mscan:
diff --git a/kernel/2.6/drivers/net/can/mscan/mscan.c 
b/kernel/2.6/drivers/net/can/mscan/mscan.c
index e5d5004..5b5fc54 100644
--- a/kernel/2.6/drivers/net/can/mscan/mscan.c
+++ b/kernel/2.6/drivers/net/can/mscan/mscan.c
@@ -101,6 +101,7 @@ struct mscan_priv {
        u8 cur_pri;
        u8 prev_buf_id;
        u8 tx_active;
+       u8 rx_mode;
 
        struct list_head tx_head;
        struct tx_queue_entry tx_queue[TX_QUEUE_SIZE];
@@ -331,22 +332,9 @@ static inline int check_set_state(struct net_device *dev, 
u8 canrflg)
        return ret;
 }
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-static int mscan_rx_poll(struct napi_struct *napi, int quota)
-#else
-static int mscan_rx_poll(struct net_device *dev, int *budget)
-#endif
+static int mscan_rx_process(struct net_device *dev, int quota)
 {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
-       struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
-       struct net_device *dev = napi->dev;
-#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-       struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
-       struct net_device *dev = priv->dev;
-#else
        struct mscan_priv *priv = netdev_priv(dev);
-       int quota = min(dev->quota, *budget);
-#endif
        struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
        struct net_device_stats *stats = can_get_stats(dev);
@@ -361,8 +349,10 @@ static int mscan_rx_poll(struct net_device *dev, int 
*budget)
        u8 canrflg;
        int i;
 
-       while (npackets < quota && ((canrflg = in_8(&regs->canrflg)) &
+       while (((canrflg = in_8(&regs->canrflg)) &
                                    (MSCAN_RXF | MSCAN_ERR_IF))) {
+               if (priv->rx_mode == RX_POLL && npackets >= quota)
+                       break;
 
                skb = alloc_can_skb(dev, &frame);
                if (!skb) {
@@ -455,16 +445,22 @@ static int mscan_rx_poll(struct net_device *dev, int 
*budget)
                        out_8(&regs->canrflg, MSCAN_ERR_IF);
                }
 
-               npackets++;
-               netif_receive_skb(skb);
+               if (priv->rx_mode == RX_POLL) {
+                       npackets++;
+                       netif_receive_skb(skb);
+               } else
+                       netif_rx(skb);
        }
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
-       *budget -= npackets;
-       dev->quota -= npackets;
+       if (priv->rx_mode == RX_POLL) {
+               *budget -= npackets;
+               dev->quota -= npackets;
+       }
 #endif
 
-       if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
+       if ((priv->rx_mode == RX_POLL) &&
+               !(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
                napi_complete(&priv->napi);
 #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
@@ -476,10 +472,30 @@ static int mscan_rx_poll(struct net_device *dev, int 
*budget)
                if (priv->can.state < CAN_STATE_BUS_OFF)
                        out_8(&regs->canrier, priv->shadow_canrier);
                ret = 0;
-       }
+       } else if (priv->rx_mode == RX_IRQ)
+               ret = 0;
+
        return ret;
 }
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+static int mscan_rx_poll(struct napi_struct *napi, int quota)
+#else
+static int mscan_rx_poll(struct net_device *dev, int *budget)
+#endif
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
+       struct net_device *dev = napi->dev;
+#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
+       struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
+       struct net_device *dev = priv->dev;
+#else
+       struct mscan_priv *priv = netdev_priv(dev);
+       int quota = min(dev->quota, *budget);
+#endif
+       mscan_rx_process(dev, quota);
+}
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
 static irqreturn_t mscan_isr(int irq, void *dev_id, struct pt_regs *r)
 #else
@@ -535,21 +551,28 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
        }
 
        canrflg = in_8(&regs->canrflg);
-       if ((canrflg & ~MSCAN_STAT_MSK) &&
-           !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) {
-               if (canrflg & ~MSCAN_STAT_MSK) {
-                       priv->shadow_canrier = in_8(&regs->canrier);
-                       out_8(&regs->canrier, 0);
+       if (canrflg & ~MSCAN_STAT_MSK) {
+               if (priv->rx_mode == RX_POLL
+                       && !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) {
+                       if (canrflg & ~MSCAN_STAT_MSK) {
+                               priv->shadow_canrier = in_8(&regs->canrier);
+                               out_8(&regs->canrier, 0);
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
-                       napi_schedule(&priv->napi);
+                               napi_schedule(&priv->napi);
 #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-                       netif_rx_schedule(dev, &priv->napi);
+                               netif_rx_schedule(dev, &priv->napi);
 #else
-                       netif_rx_schedule(dev);
+                               netif_rx_schedule(dev);
 #endif
+                               ret = IRQ_HANDLED;
+                       } else
+                               clear_bit(F_RX_PROGRESS, &priv->flags);
+               }
+
+               if (priv->rx_mode == RX_IRQ) {
+                       mscan_rx_process(dev, 0);
                        ret = IRQ_HANDLED;
-               } else
-                       clear_bit(F_RX_PROGRESS, &priv->flags);
+               }
        }
        return ret;
 }
@@ -621,13 +644,15 @@ static int mscan_open(struct net_device *dev)
                return ret;
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-       napi_enable(&priv->napi);
+       if (priv->rx_mode == RX_POLL)
+               napi_enable(&priv->napi);
 #endif
 
        ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);
        if (ret < 0) {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-               napi_disable(&priv->napi);
+               if (priv->rx_mode == RX_POLL)
+                       napi_disable(&priv->napi);
 #endif
                printk(KERN_ERR "%s - failed to attach interrupt\n",
                       dev->name);
@@ -654,7 +679,8 @@ static int mscan_close(struct net_device *dev)
 
        netif_stop_queue(dev);
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
-       napi_disable(&priv->napi);
+       if (priv->rx_mode == RX_POLL)
+               napi_disable(&priv->napi);
 #endif
 
        out_8(&regs->cantier, 0);
@@ -718,7 +744,7 @@ void unregister_mscandev(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(unregister_mscandev);
 
-struct net_device *alloc_mscandev(void)
+struct net_device *alloc_mscandev(int rx_mode)
 {
        struct net_device *dev;
        struct mscan_priv *priv;
@@ -729,6 +755,8 @@ struct net_device *alloc_mscandev(void)
                return NULL;
        priv = netdev_priv(dev);
 
+       priv->rx_mode = rx_mode;
+
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
        dev->netdev_ops = &mscan_netdev_ops;
 #else
@@ -740,13 +768,17 @@ struct net_device *alloc_mscandev(void)
        dev->flags |= IFF_ECHO; /* we support local echo */
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
-       netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
+       if (priv->rx_mode == RX_POLL)
+               netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
 #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
        priv->dev = dev;
-       netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
+       if (priv->rx_mode == RX_POLL)
+               netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
 #else
-       dev->poll = mscan_rx_poll;
-       dev->weight = 8;
+       if (priv->rx_mode == RX_POLL) {
+               dev->poll = mscan_rx_poll;
+               dev->weight = 8;
+       }
 #endif
 
        priv->can.bittiming_const = &mscan_bittiming_const;
diff --git a/kernel/2.6/drivers/net/can/mscan/mscan.h 
b/kernel/2.6/drivers/net/can/mscan/mscan.h
index f352466..51b1c2f 100644
--- a/kernel/2.6/drivers/net/can/mscan/mscan.h
+++ b/kernel/2.6/drivers/net/can/mscan/mscan.h
@@ -238,7 +238,10 @@ struct mscan_platform_data {
 };
 #endif
 
-struct net_device *alloc_mscandev(void);
+#define RX_POLL 0
+#define RX_IRQ 1
+struct net_device *alloc_mscandev(int rx_mode);
+
 /*
  * clock_src:
  *     1 = The MSCAN clock source is the onchip Bus Clock.
-- 
1.6.5

_______________________________________________
Socketcan-users mailing list
Socketcan-users@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/socketcan-users

Reply via email to