On Fri, Oct 30, 2009 at 12:27:53PM +0100, Luotao Fu wrote:
> 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.
> 

doh! sent a patch with incomplete patch header. attached the one with
corrected header with this mail.

Cheers
Fu
-- 
Pengutronix e.K.                           | Dipl.-Ing. Luotao Fu        |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
From 9defd39157a26cbd7644b0e5507152586a019612 Mon Sep 17 00:00:00 2001
From: Luotao Fu <[email protected]>
Date: Fri, 30 Oct 2009 12:17:49 +0100
Subject: [PATCH] mscan: add non-polling rx

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. If there're more than one can interface registered.
Every interface can have different rx mode.

This patch is a rework of an original version by Vladislav Gribov for socketcan
-r466. Tested on 2.6.23 and 2.6.31, please review.

Signed-off-by: Luotao Fu <[email protected]>
---
 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

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users

Reply via email to