All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading
@ 2015-09-01  9:29 Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 01/12] can: headers: make header files self contained Marc Kleine-Budde
                   ` (11 more replies)
  0 siblings, 12 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david

Hello,

this series picks up David Jander's idea to introduce a simple IRQ offloading
mechanism. The idea is to offer a mechanism for  hardware FIFO (or single RX
buffer) based CAN cores to read the CAN frames in the interrupt handler but
defer sending into normal NAPI context.

This series first cleans up the flexcan driver, then adds the generic IRQ
offloading code and finally switches the flexcan driver to use it.

Testing and feedback welcome.

regards,
Marc


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/12] can: headers: make header files self contained
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 02/12] can: flexcan: cleanup coding style and fix typos Marc Kleine-Budde
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch adds the missing #include-s to the dev.h and led.h, so that they can
be used without including further header files.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 include/linux/can/dev.h | 3 ++-
 include/linux/can/led.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index c3a9c8fc60fa..56dcadd83716 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -14,9 +14,10 @@
 #define _CAN_DEV_H
 
 #include <linux/can.h>
-#include <linux/can/netlink.h>
 #include <linux/can/error.h>
 #include <linux/can/led.h>
+#include <linux/can/netlink.h>
+#include <linux/netdevice.h>
 
 /*
  * CAN mode
diff --git a/include/linux/can/led.h b/include/linux/can/led.h
index 146de4506d21..2746f7c2f87d 100644
--- a/include/linux/can/led.h
+++ b/include/linux/can/led.h
@@ -11,6 +11,7 @@
 
 #include <linux/if.h>
 #include <linux/leds.h>
+#include <linux/netdevice.h>
 
 enum can_led_event {
 	CAN_LED_EVENT_OPEN,
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/12] can: flexcan: cleanup coding style and fix typos
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 01/12] can: headers: make header files self contained Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 03/12] can: flexcan: remove unused header files Marc Kleine-Budde
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch fixes up the coding style to make checkpatch happier. Some typos are
also fixed.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 90 ++++++++++++++++++++---------------------------
 1 file changed, 38 insertions(+), 52 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index c83f0f03482b..e9e8f095461c 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -63,10 +63,10 @@
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
 #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
-#define FLEXCAN_MCR_IDAM_A		(0 << 8)
-#define FLEXCAN_MCR_IDAM_B		(1 << 8)
-#define FLEXCAN_MCR_IDAM_C		(2 << 8)
-#define FLEXCAN_MCR_IDAM_D		(3 << 8)
+#define FLEXCAN_MCR_IDAM_A		(0x0 << 8)
+#define FLEXCAN_MCR_IDAM_B		(0x1 << 8)
+#define FLEXCAN_MCR_IDAM_C		(0x2 << 8)
+#define FLEXCAN_MCR_IDAM_D		(0x3 << 8)
 
 /* FLEXCAN control register (CANCTRL) bits */
 #define FLEXCAN_CTRL_PRESDIV(x)		(((x) & 0xff) << 24)
@@ -161,7 +161,7 @@
 #define FLEXCAN_MB_CODE_RX_INACTIVE	(0x0 << 24)
 #define FLEXCAN_MB_CODE_RX_EMPTY	(0x4 << 24)
 #define FLEXCAN_MB_CODE_RX_FULL		(0x2 << 24)
-#define FLEXCAN_MB_CODE_RX_OVERRRUN	(0x6 << 24)
+#define FLEXCAN_MB_CODE_RX_OVERRUN	(0x6 << 24)
 #define FLEXCAN_MB_CODE_RX_RANSWER	(0xa << 24)
 
 #define FLEXCAN_MB_CODE_TX_INACTIVE	(0x8 << 24)
@@ -175,12 +175,9 @@
 #define FLEXCAN_MB_CNT_LENGTH(x)	(((x) & 0xf) << 16)
 #define FLEXCAN_MB_CNT_TIMESTAMP(x)	((x) & 0xffff)
 
-#define FLEXCAN_MB_CODE_MASK		(0xf0ffffff)
+#define FLEXCAN_TIMEOUT_US		(50)
 
-#define FLEXCAN_TIMEOUT_US             (50)
-
-/*
- * FLEXCAN hardware feature flags
+/* FLEXCAN hardware feature flags
  *
  * Below is some version info we got:
  *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT Memory err RTR re-
@@ -236,7 +233,7 @@ struct flexcan_regs {
 	 * 0x0e0...0x0ff	6-7	8 entry ID table
 	 *				(mx25, mx28, mx35, mx53)
 	 * 0x0e0...0x2df	6-7..37	8..128 entry ID table
-	 *			  	size conf'ed via ctrl2::RFFN
+	 *				size conf'ed via ctrl2::RFFN
 	 *				(mx6, vf610)
 	 */
 	u32 _reserved4[408];
@@ -272,10 +269,13 @@ struct flexcan_priv {
 static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 	.features = FLEXCAN_HAS_BROKEN_ERR_STATE,
 };
+
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
+
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
 	.features = FLEXCAN_HAS_V10_FEATURES,
 };
+
 static struct flexcan_devtype_data fsl_vf610_devtype_data = {
 	.features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES,
 };
@@ -292,11 +292,10 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
 	.brp_inc = 1,
 };
 
-/*
- * Abstract off the read/write for arm versus ppc. This
+/* Abstract off the read/write for arm versus ppc. This
  * assumes that PPC uses big-endian registers and everything
  * else uses little-endian registers, independent of CPU
- * endianess.
+ * endianness.
  */
 #if defined(CONFIG_PPC)
 static inline u32 flexcan_read(void __iomem *addr)
@@ -434,7 +433,6 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)
 	return 0;
 }
 
-
 static int __flexcan_get_berr_counter(const struct net_device *dev,
 				      struct can_berr_counter *bec)
 {
@@ -477,6 +475,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct flexcan_regs __iomem *regs = priv->base;
 	struct can_frame *cf = (struct can_frame *)skb->data;
 	u32 can_id;
+	u32 data;
 	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
 
 	if (can_dropped_invalid_skb(dev, skb))
@@ -495,11 +494,11 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		ctrl |= FLEXCAN_MB_CNT_RTR;
 
 	if (cf->can_dlc > 0) {
-		u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
+		data = be32_to_cpup((__be32 *)&cf->data[0]);
 		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
 	}
 	if (cf->can_dlc > 3) {
-		u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
+		data = be32_to_cpup((__be32 *)&cf->data[4]);
 		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
 	}
 
@@ -597,14 +596,14 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
 	flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
 	if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
 		tx_state = unlikely(reg_esr & FLEXCAN_ESR_TX_WRN) ?
-			   CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+			CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
 		rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
-			   CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
+			CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
 		new_state = max(tx_state, rx_state);
 	} else {
 		__flexcan_get_berr_counter(dev, &bec);
 		new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ?
-			    CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
+			CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
 		rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
 		tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
 	}
@@ -687,8 +686,7 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
 	u32 reg_iflag1, reg_esr;
 	int work_done = 0;
 
-	/*
-	 * The error bits are cleared on read,
+	/* The error bits are cleared on read,
 	 * use saved value from irq handler.
 	 */
 	reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
@@ -728,12 +726,12 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
 	reg_iflag1 = flexcan_read(&regs->iflag1);
 	reg_esr = flexcan_read(&regs->esr);
+
 	/* ACK all bus error and state change IRQ sources */
 	if (reg_esr & FLEXCAN_ESR_ALL_INT)
 		flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
 
-	/*
-	 * schedule NAPI in case of:
+	/* schedule NAPI in case of:
 	 * - rx IRQ
 	 * - state change IRQ
 	 * - bus error IRQ and bus error reporting is activated
@@ -741,15 +739,14 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) ||
 	    (reg_esr & FLEXCAN_ESR_ERR_STATE) ||
 	    flexcan_has_and_handle_berr(priv, reg_esr)) {
-		/*
-		 * The error bits are cleared on read,
+		/* The error bits are cleared on read,
 		 * save them for later use.
 		 */
 		priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
 		flexcan_write(FLEXCAN_IFLAG_DEFAULT &
-			~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
+			      ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
 		flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
-		       &regs->ctrl);
+			      &regs->ctrl);
 		napi_schedule(&priv->napi);
 	}
 
@@ -765,7 +762,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		stats->tx_bytes += can_get_echo_skb(dev, 0);
 		stats->tx_packets++;
 		can_led_event(dev, CAN_LED_EVENT_TX);
-		/* after sending a RTR frame mailbox is in RX mode */
+
+		/* after sending a RTR frame MB is in RX mode */
 		flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
 			      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
 		flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
@@ -813,8 +811,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
 		   flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
 }
 
-/*
- * flexcan_chip_start
+/* flexcan_chip_start
  *
  * this functions is entered with clocks enabled
  *
@@ -838,8 +835,7 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	flexcan_set_bittiming(dev);
 
-	/*
-	 * MCR
+	/* MCR
 	 *
 	 * enable freeze
 	 * enable fifo
@@ -848,7 +844,6 @@ static int flexcan_chip_start(struct net_device *dev)
 	 * enable warning int
 	 * choose format C
 	 * disable local echo
-	 *
 	 */
 	reg_mcr = flexcan_read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
@@ -859,8 +854,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	flexcan_write(reg_mcr, &regs->mcr);
 
-	/*
-	 * CTRL
+	/* CTRL
 	 *
 	 * disable timer sync feature
 	 *
@@ -875,8 +869,8 @@ static int flexcan_chip_start(struct net_device *dev)
 	reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
 	reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
 		FLEXCAN_CTRL_ERR_STATE;
-	/*
-	 * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
+
+	/* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
 	 * on most Flexcan cores, too. Otherwise we don't get
 	 * any error warning or passive interrupts.
 	 */
@@ -913,16 +907,14 @@ static int flexcan_chip_start(struct net_device *dev)
 	if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
 		flexcan_write(0x0, &regs->rxfgmask);
 
-	/*
-	 * On Vybrid, disable memory error detection interrupts
+	/* On Vybrid, disable memory error detection interrupts
 	 * and freeze mode.
 	 * This also works around errata e5295 which generates
 	 * false positive memory errors and put the device in
 	 * freeze mode.
 	 */
 	if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) {
-		/*
-		 * Follow the protocol as described in "Detection
+		/* Follow the protocol as described in "Detection
 		 * and Correction of Memory Errors" to write to
 		 * MECR register
 		 */
@@ -934,7 +926,7 @@ static int flexcan_chip_start(struct net_device *dev)
 		reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
 		flexcan_write(reg_mecr, &regs->mecr);
 		reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
-				FLEXCAN_MECR_FANCEI_MSK);
+			      FLEXCAN_MECR_FANCEI_MSK);
 		flexcan_write(reg_mecr, &regs->mecr);
 	}
 
@@ -965,11 +957,9 @@ static int flexcan_chip_start(struct net_device *dev)
 	return err;
 }
 
-/*
- * flexcan_chip_stop
+/* flexcan_chip_stop
  *
  * this functions is entered with clocks enabled
- *
  */
 static void flexcan_chip_stop(struct net_device *dev)
 {
@@ -987,8 +977,6 @@ static void flexcan_chip_stop(struct net_device *dev)
 
 	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
-
-	return;
 }
 
 static int flexcan_open(struct net_device *dev)
@@ -1114,8 +1102,7 @@ static int register_flexcandev(struct net_device *dev)
 		FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
 	flexcan_write(reg, &regs->mcr);
 
-	/*
-	 * Currently we only support newer versions of this core
+	/* Currently we only support newer versions of this core
 	 * featuring a RX FIFO. Older cores found on some Coldfire
 	 * derivates are not yet supported.
 	 */
@@ -1180,7 +1167,7 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	if (pdev->dev.of_node)
 		of_property_read_u32(pdev->dev.of_node,
-						"clock-frequency", &clock_freq);
+				     "clock-frequency", &clock_freq);
 
 	if (!clock_freq) {
 		clk_ipg = devm_clk_get(&pdev->dev, "ipg");
@@ -1237,7 +1224,6 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->clk_per = clk_per;
 	priv->pdata = dev_get_platdata(&pdev->dev);
 	priv->devtype_data = devtype_data;
-
 	priv->reg_xceiver = reg_xceiver;
 
 	netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/12] can: flexcan: remove unused header files
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 01/12] can: headers: make header files self contained Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 02/12] can: flexcan: cleanup coding style and fix typos Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 04/12] can: flexcan: flexcan_chip_start(): cleanup writing of reg_mcr Marc Kleine-Budde
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch removes unused header files from the flexcan driver.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index e9e8f095461c..83ea6f4f7164 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -26,12 +26,8 @@
 #include <linux/can/led.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/12] can: flexcan: flexcan_chip_start(): cleanup writing of reg_mcr
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 03/12] can: flexcan: remove unused header files Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 05/12] can: flexcan: rename feature into quirks Marc Kleine-Budde
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch changes the order the individual bits of the mcr register in
flexcan_chip_start() are or'ed together to match the datasheet. The inline
documentation is adjusted accordingly.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 83ea6f4f7164..70cdbfcebb46 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -838,15 +838,15 @@ static int flexcan_chip_start(struct net_device *dev)
 	 * halt now
 	 * only supervisor access
 	 * enable warning int
-	 * choose format C
 	 * disable local echo
+	 * choose format C
+	 * set max mailbox number
 	 */
 	reg_mcr = flexcan_read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
-		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
-		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS |
-		FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
+		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	flexcan_write(reg_mcr, &regs->mcr);
 
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/12] can: flexcan: rename feature into quirks
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 04/12] can: flexcan: flexcan_chip_start(): cleanup writing of reg_mcr Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 06/12] can: flexcan: use pointer to struct regs instead of void pointer for mmio address space Marc Kleine-Budde
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch renames the "features" member of struct flexcan_devtype_data to
"quirks". The corresponding defines are renamed too, to reflect what they
actually do.

    FLEXCAN_HAS_V10_FEATURES      -> FLEXCAN_QUIRK_DISABLE_RXFG
    FLEXCAN_HAS_BROKEN_ERR_STATE  -> FLEXCAN_QUIRK_BROKEN_ERR_STATE
    FLEXCAN_HAS_MECR_FEATURES     -> FLEXCAN_QUIRK_DISABLE_MECR

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 70cdbfcebb46..dd5a9353e0c5 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -187,9 +187,9 @@
  *
  * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
  */
-#define FLEXCAN_HAS_V10_FEATURES	BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE	BIT(2) /* [TR]WRN_INT not connected */
-#define FLEXCAN_HAS_MECR_FEATURES	BIT(3) /* Memory error detection */
+#define FLEXCAN_QUIRK_BROKEN_ERR_STATE	BIT(1) /* [TR]WRN_INT not connected */
+#define FLEXCAN_QUIRK_DISABLE_RXFG	BIT(2) /* Disable RX FIFO Global mask */
+#define FLEXCAN_QUIRK_DISABLE_MECR	BIT(3) /* Disble Memory error detection */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -244,7 +244,7 @@ struct flexcan_regs {
 };
 
 struct flexcan_devtype_data {
-	u32 features;	/* hardware controller features */
+	u32 quirks;		/* quirks needed for different IP cores */
 };
 
 struct flexcan_priv {
@@ -263,17 +263,17 @@ struct flexcan_priv {
 };
 
 static struct flexcan_devtype_data fsl_p1010_devtype_data = {
-	.features = FLEXCAN_HAS_BROKEN_ERR_STATE,
+	.quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE,
 };
 
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-	.features = FLEXCAN_HAS_V10_FEATURES,
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG,
 };
 
 static struct flexcan_devtype_data fsl_vf610_devtype_data = {
-	.features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES,
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -870,7 +870,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	 * on most Flexcan cores, too. Otherwise we don't get
 	 * any error warning or passive interrupts.
 	 */
-	if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE ||
 	    priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
 		reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
 	else
@@ -900,7 +900,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	flexcan_write(0x0, &regs->rx14mask);
 	flexcan_write(0x0, &regs->rx15mask);
 
-	if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
 		flexcan_write(0x0, &regs->rxfgmask);
 
 	/* On Vybrid, disable memory error detection interrupts
@@ -909,7 +909,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	 * false positive memory errors and put the device in
 	 * freeze mode.
 	 */
-	if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) {
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) {
 		/* Follow the protocol as described in "Detection
 		 * and Correction of Memory Errors" to write to
 		 * MECR register
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/12] can: flexcan: use pointer to struct regs instead of void pointer for mmio address space
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 05/12] can: flexcan: rename feature into quirks Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 07/12] can: flexcan: give member of flexcan_priv holding mailboxes a sensible name Marc Kleine-Budde
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch renames the pointer to the mmio address space from "base" to "regs"
and changes the type from "void __iomem *" to "struct flexcan_regs __iomem *".

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index dd5a9353e0c5..72831c52ff53 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -251,7 +251,7 @@ struct flexcan_priv {
 	struct can_priv can;
 	struct napi_struct napi;
 
-	void __iomem *base;
+	struct flexcan_regs __iomem *regs;
 	u32 reg_esr;
 	u32 reg_ctrl_default;
 
@@ -340,7 +340,7 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
 
 static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
@@ -359,7 +359,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
 
 static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
@@ -378,7 +378,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
 
 static int flexcan_chip_freeze(struct flexcan_priv *priv)
 {
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
 	u32 reg;
 
@@ -397,7 +397,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
 
 static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
 {
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
@@ -416,7 +416,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
 
 static int flexcan_chip_softreset(struct flexcan_priv *priv)
 {
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 
 	flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
@@ -433,7 +433,7 @@ static int __flexcan_get_berr_counter(const struct net_device *dev,
 				      struct can_berr_counter *bec)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg = flexcan_read(&regs->ecr);
 
 	bec->txerr = (reg >> 0) & 0xff;
@@ -468,7 +468,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct can_frame *cf = (struct can_frame *)skb->data;
 	u32 can_id;
 	u32 data;
@@ -628,7 +628,7 @@ static void flexcan_read_fifo(const struct net_device *dev,
 			      struct can_frame *cf)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
 	u32 reg_ctrl, reg_id;
 
@@ -678,7 +678,7 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
 {
 	struct net_device *dev = napi->dev;
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg_iflag1, reg_esr;
 	int work_done = 0;
 
@@ -717,7 +717,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	struct net_device *dev = dev_id;
 	struct net_device_stats *stats = &dev->stats;
 	struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg_iflag1, reg_esr;
 
 	reg_iflag1 = flexcan_read(&regs->iflag1);
@@ -773,7 +773,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
 	const struct can_bittiming *bt = &priv->can.bittiming;
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg;
 
 	reg = flexcan_read(&regs->ctrl);
@@ -815,7 +815,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
 static int flexcan_chip_start(struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
 	int err, i;
 
@@ -960,7 +960,7 @@ static int flexcan_chip_start(struct net_device *dev)
 static void flexcan_chip_stop(struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 
 	/* freeze + disable module */
 	flexcan_chip_freeze(priv);
@@ -1069,7 +1069,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
 static int register_flexcandev(struct net_device *dev)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->base;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	u32 reg, err;
 
 	err = clk_prepare_enable(priv->clk_ipg);
@@ -1151,7 +1151,7 @@ static int flexcan_probe(struct platform_device *pdev)
 	struct regulator *reg_xceiver;
 	struct resource *mem;
 	struct clk *clk_ipg = NULL, *clk_per = NULL;
-	void __iomem *base;
+	struct flexcan_regs __iomem *regs;
 	int err, irq;
 	u32 clock_freq = 0;
 
@@ -1185,9 +1185,9 @@ static int flexcan_probe(struct platform_device *pdev)
 	if (irq <= 0)
 		return -ENODEV;
 
-	base = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
 
 	of_id = of_match_device(flexcan_of_match, &pdev->dev);
 	if (of_id) {
@@ -1215,7 +1215,7 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
 		CAN_CTRLMODE_LISTENONLY	| CAN_CTRLMODE_3_SAMPLES |
 		CAN_CTRLMODE_BERR_REPORTING;
-	priv->base = base;
+	priv->regs = regs;
 	priv->clk_ipg = clk_ipg;
 	priv->clk_per = clk_per;
 	priv->pdata = dev_get_platdata(&pdev->dev);
@@ -1236,7 +1236,7 @@ static int flexcan_probe(struct platform_device *pdev)
 	devm_can_led_init(dev);
 
 	dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
-		 priv->base, dev->irq);
+		 priv->regs, dev->irq);
 
 	return 0;
 
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/12] can: flexcan: give member of flexcan_priv holding mailboxes a sensible name
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 06/12] can: flexcan: use pointer to struct regs instead of void pointer for mmio address space Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 08/12] can: flexcan: enable interrupts atomically at the end of flexcan_chip_start() Marc Kleine-Budde
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch gives the member of flexcan_priv holding mailboxes a sensible name,
by renaming from "cantxfg" to "mb":

    struct flexcan_priv::cantxfg -> struct flexcan_priv::mb

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 72831c52ff53..28b6283aacf2 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -221,7 +221,7 @@ struct flexcan_regs {
 	u32 rxfgmask;		/* 0x48 */
 	u32 rxfir;		/* 0x4c */
 	u32 _reserved3[12];	/* 0x50 */
-	struct flexcan_mb cantxfg[64];	/* 0x80 */
+	struct flexcan_mb mb[64];	/* 0x80 */
 	/* FIFO-mode:
 	 *			MB
 	 * 0x080...0x08f	0	RX message buffer
@@ -491,25 +491,25 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (cf->can_dlc > 0) {
 		data = be32_to_cpup((__be32 *)&cf->data[0]);
-		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
+		flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[0]);
 	}
 	if (cf->can_dlc > 3) {
 		data = be32_to_cpup((__be32 *)&cf->data[4]);
-		flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
+		flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[1]);
 	}
 
 	can_put_echo_skb(skb, dev, 0);
 
-	flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
-	flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+	flexcan_write(can_id, &regs->mb[FLEXCAN_TX_BUF_ID].can_id);
+	flexcan_write(ctrl, &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
 
 	/* Errata ERR005829 step8:
 	 * Write twice INACTIVE(0x8) code to first MB.
 	 */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
 
 	return NETDEV_TX_OK;
 }
@@ -629,7 +629,7 @@ static void flexcan_read_fifo(const struct net_device *dev,
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->regs;
-	struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
+	struct flexcan_mb __iomem *mb = &regs->mb[0];
 	u32 reg_ctrl, reg_id;
 
 	reg_ctrl = flexcan_read(&mb->can_ctrl);
@@ -761,7 +761,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
 		/* after sending a RTR frame MB is in RX mode */
 		flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-			      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+			      &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
 		flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
 		netif_wake_queue(dev);
 	}
@@ -882,18 +882,18 @@ static int flexcan_chip_start(struct net_device *dev)
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
 	/* clear and invalidate all mailboxes first */
-	for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) {
+	for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
 		flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
-			      &regs->cantxfg[i].can_ctrl);
+			      &regs->mb[i].can_ctrl);
 	}
 
 	/* Errata ERR005829: mark first TX mailbox as INACTIVE */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
 
 	/* mark TX mailbox as INACTIVE */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+		      &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
 
 	/* acceptance mask/acceptance code (accept everything) */
 	flexcan_write(0x0, &regs->rxgmask);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/12] can: flexcan: enable interrupts atomically at the end of flexcan_chip_start()
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 07/12] can: flexcan: give member of flexcan_priv holding mailboxes a sensible name Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 09/12] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch defers the writing of the interrupts bits of the CTRL register order
to enables all interrupts atomically at the the of the flexcan_chip_start()
function.

Suggested-by: Torsten Lang <torsten.lang@uweschneider.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 28b6283aacf2..868fe945e35a 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -878,6 +878,8 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	/* save for later use */
 	priv->reg_ctrl_default = reg_ctrl;
+	/* leave interrupts disabled for now */
+	reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL;
 	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
@@ -937,8 +939,11 @@ static int flexcan_chip_start(struct net_device *dev)
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
-	/* enable FIFO interrupts */
+	/* enable interrupts atomically */
+	disable_irq(dev->irq);
+	flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
 	flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+	enable_irq(dev->irq);
 
 	/* print chip status */
 	netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__,
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/12] can: flexcan: calculate default value for imask1 during runtime
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 08/12] can: flexcan: enable interrupts atomically at the end of flexcan_chip_start() Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 10/12] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch converts the define FLEXCAN_IFLAG_DEFAULT into the runtime
calculated value priv->reg_imask1_default. This is a preparation patch to make
the TX mailbox selectable during runtime, too.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 868fe945e35a..c54c35e9b02f 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -149,9 +149,6 @@
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)
 #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE	BIT(5)
-#define FLEXCAN_IFLAG_DEFAULT \
-	(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW | FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | \
-	 FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID))
 
 /* FLEXCAN message buffers */
 #define FLEXCAN_MB_CODE_RX_INACTIVE	(0x0 << 24)
@@ -254,6 +251,7 @@ struct flexcan_priv {
 	struct flexcan_regs __iomem *regs;
 	u32 reg_esr;
 	u32 reg_ctrl_default;
+	u32 reg_imask1_default;
 
 	struct clk *clk_ipg;
 	struct clk *clk_per;
@@ -705,7 +703,7 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
 	if (work_done < quota) {
 		napi_complete(napi);
 		/* enable IRQs */
-		flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+		flexcan_write(priv->reg_imask1_default, &regs->imask1);
 		flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
 	}
 
@@ -739,7 +737,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		 * save them for later use.
 		 */
 		priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
-		flexcan_write(FLEXCAN_IFLAG_DEFAULT &
+		flexcan_write(priv->reg_imask1_default &
 			      ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
 		flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 			      &regs->ctrl);
@@ -942,7 +940,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	/* enable interrupts atomically */
 	disable_irq(dev->irq);
 	flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
-	flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
+	flexcan_write(priv->reg_imask1_default, &regs->imask1);
 	enable_irq(dev->irq);
 
 	/* print chip status */
@@ -1227,6 +1225,10 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->devtype_data = devtype_data;
 	priv->reg_xceiver = reg_xceiver;
 
+	priv->reg_imask1_default = FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
+		FLEXCAN_IFLAG_RX_FIFO_AVAILABLE |
+		FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID);
+
 	netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
 
 	platform_set_drvdata(pdev, dev);
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/12] can: flexcan: make TX mailbox selectable during runtime
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 09/12] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 11/12] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 12/12] can: flexcan: make use of rx-fifos's irq_offload_simple Marc Kleine-Budde
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch makes the TX mailbox selectable duing runtime. This is a preparation
patch to use of the hardware FIFO selectable via runtime. As the TX mailbox
number is different in HW FIFO and normal mode.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 42 ++++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index c54c35e9b02f..a62bc43807c8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -143,9 +143,9 @@
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
-#define FLEXCAN_TX_BUF_RESERVED		8
-#define FLEXCAN_TX_BUF_ID		9
-#define FLEXCAN_IFLAG_BUF(x)		BIT(x)
+#define FLEXCAN_TX_MB_RESERVED_HW_FIFO	8
+#define FLEXCAN_TX_MB_HW_FIFO		9
+#define FLEXCAN_IFLAG_MB(x)		BIT(x)
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)
 #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE	BIT(5)
@@ -249,6 +249,9 @@ struct flexcan_priv {
 	struct napi_struct napi;
 
 	struct flexcan_regs __iomem *regs;
+	struct flexcan_mb __iomem *tx_mb;
+	struct flexcan_mb __iomem *tx_mb_reserved;
+	u8 tx_mb_idx;
 	u32 reg_esr;
 	u32 reg_ctrl_default;
 	u32 reg_imask1_default;
@@ -466,7 +469,6 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct flexcan_regs __iomem *regs = priv->regs;
 	struct can_frame *cf = (struct can_frame *)skb->data;
 	u32 can_id;
 	u32 data;
@@ -489,25 +491,25 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (cf->can_dlc > 0) {
 		data = be32_to_cpup((__be32 *)&cf->data[0]);
-		flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[0]);
+		flexcan_write(data, &priv->tx_mb->data[0]);
 	}
 	if (cf->can_dlc > 3) {
 		data = be32_to_cpup((__be32 *)&cf->data[4]);
-		flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[1]);
+		flexcan_write(data, &priv->tx_mb->data[1]);
 	}
 
 	can_put_echo_skb(skb, dev, 0);
 
-	flexcan_write(can_id, &regs->mb[FLEXCAN_TX_BUF_ID].can_id);
-	flexcan_write(ctrl, &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
+	flexcan_write(can_id, &priv->tx_mb->can_id);
+	flexcan_write(ctrl, &priv->tx_mb->can_ctrl);
 
 	/* Errata ERR005829 step8:
 	 * Write twice INACTIVE(0x8) code to first MB.
 	 */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &priv->tx_mb_reserved->can_ctrl);
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &priv->tx_mb_reserved->can_ctrl);
 
 	return NETDEV_TX_OK;
 }
@@ -752,15 +754,15 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	}
 
 	/* transmission complete interrupt */
-	if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
+	if (reg_iflag1 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
 		stats->tx_bytes += can_get_echo_skb(dev, 0);
 		stats->tx_packets++;
 		can_led_event(dev, CAN_LED_EVENT_TX);
 
 		/* after sending a RTR frame MB is in RX mode */
 		flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-			      &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
-		flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
+			      &priv->tx_mb->can_ctrl);
+		flexcan_write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag1);
 		netif_wake_queue(dev);
 	}
 
@@ -844,7 +846,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
 		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
-		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	flexcan_write(reg_mcr, &regs->mcr);
 
@@ -882,18 +884,18 @@ static int flexcan_chip_start(struct net_device *dev)
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
 	/* clear and invalidate all mailboxes first */
-	for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
+	for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) {
 		flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
 			      &regs->mb[i].can_ctrl);
 	}
 
 	/* Errata ERR005829: mark first TX mailbox as INACTIVE */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
+		      &priv->tx_mb_reserved->can_ctrl);
 
 	/* mark TX mailbox as INACTIVE */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
-		      &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
+		      &priv->tx_mb->can_ctrl);
 
 	/* acceptance mask/acceptance code (accept everything) */
 	flexcan_write(0x0, &regs->rxgmask);
@@ -1225,9 +1227,13 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->devtype_data = devtype_data;
 	priv->reg_xceiver = reg_xceiver;
 
+	priv->tx_mb_idx = FLEXCAN_TX_MB_HW_FIFO;
+	priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_HW_FIFO];
+	priv->tx_mb = &regs->mb[priv->tx_mb_idx];
+
 	priv->reg_imask1_default = FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
 		FLEXCAN_IFLAG_RX_FIFO_AVAILABLE |
-		FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID);
+		FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
 
 	netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
 
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/12] can: rx-fifo: Add support for simple irq offloading
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 10/12] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
  2015-09-01  9:29 ` [PATCH 12/12] can: flexcan: make use of rx-fifos's irq_offload_simple Marc Kleine-Budde
  11 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

From: David Jander <david@protonic.nl>

Some CAN controllers have a usable FIFO already but can still benefit from
off-loading the CAN controller FIFO. The mailboxes of the FIFO  are copied to a
ring buffer during the interrupt and then transmitted in a NAPI context.

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/Makefile    |   3 +-
 drivers/net/can/rx-fifo.c   | 180 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/can/rx-fifo.h |  58 ++++++++++++++
 3 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/can/rx-fifo.c
 create mode 100644 include/linux/can/rx-fifo.h

diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index c533c62b0f5e..8b3f6e96e4ba 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
 
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
-can-dev-y			:= dev.o
+can-dev-y			+= dev.o
+can-dev-y			+= rx-fifo.o
 
 can-dev-$(CONFIG_CAN_LEDS)	+= led.o
 
diff --git a/drivers/net/can/rx-fifo.c b/drivers/net/can/rx-fifo.c
new file mode 100644
index 000000000000..2a0fb37f1bbb
--- /dev/null
+++ b/drivers/net/can/rx-fifo.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014 David Jander, Protonic Holland
+ * Copyright (C) 2014, 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/can/dev.h>
+#include <linux/can/rx-fifo.h>
+
+static int can_rx_fifo_napi_read_frame(struct can_rx_fifo *fifo, int index)
+{
+	struct net_device *dev = fifo->dev;
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+
+	skb = alloc_can_skb(dev, &cf);
+	if (unlikely(!skb)) {
+		stats->rx_dropped++;
+		return 0;
+	}
+
+	memcpy(cf, &fifo->ring[index], sizeof(*cf));
+	memset(&fifo->ring[index], 0x0, sizeof(*cf));
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+	netif_receive_skb(skb);
+
+	return 1;
+}
+
+static int can_rx_fifo_napi_poll(struct napi_struct *napi, int quota)
+{
+	struct can_rx_fifo *fifo = container_of(napi, struct can_rx_fifo, napi);
+	unsigned int tail;
+	int work_done = 0;
+
+	if (fifo->poll_pre_read && work_done < quota)
+		work_done += fifo->poll_pre_read(fifo);
+
+	/* handle mailboxes */
+	tail = fifo->ring_tail;
+	while ((CIRC_CNT(smp_load_acquire(&fifo->ring_head), tail, fifo->ring_size)) &&
+	       (work_done < quota)) {
+		work_done += can_rx_fifo_napi_read_frame(fifo, tail);
+		tail++;
+		tail &= fifo->ring_size -1;
+		smp_store_release(&fifo->ring_tail, tail);
+	}
+
+	if (fifo->poll_post_read && work_done < quota)
+		work_done += fifo->poll_post_read(fifo);
+
+	if (work_done < quota) {
+		unsigned int head;
+
+		napi_complete(napi);
+
+		/* Check if there was another interrupt */
+		head = smp_load_acquire(&fifo->ring_head);
+		if (((CIRC_CNT(head, tail, fifo->ring_size)) || fifo->poll_errors) &&
+		    napi_reschedule(&fifo->napi)) {
+			fifo->poll_errors = false;
+		}
+
+		if (fifo->poll_error_interrupts_enable)
+			fifo->poll_error_interrupts_enable(fifo);
+	}
+
+	can_led_event(fifo->dev, CAN_LED_EVENT_RX);
+
+	return work_done;
+}
+
+static unsigned int can_rx_fifo_offload_one(struct can_rx_fifo *fifo, unsigned int n)
+{
+	unsigned int head, tail;
+	unsigned int ret;
+
+	head = fifo->ring_head;
+	tail = ACCESS_ONCE(fifo->ring_tail);
+	if (CIRC_SPACE(head, tail, fifo->ring_size)) {
+		ret = fifo->mailbox_read(fifo, &fifo->ring[head], n);
+		if (ret) {
+			head++;
+			head &= fifo->ring_size - 1;
+			smp_store_release(&fifo->ring_head, head);
+		}
+	} else {
+		/* Circular buffer is fill, read to discard mailbox */
+		ret = fifo->mailbox_read(fifo, &fifo->overflow, n);
+		if (ret)
+			fifo->dev->stats.rx_dropped++;
+	}
+
+	return ret;
+}
+
+int can_rx_fifo_irq_offload_simple(struct can_rx_fifo *fifo)
+{
+	unsigned int received = 0;
+	unsigned int ret;
+
+	do {
+		ret = can_rx_fifo_offload_one(fifo, 0);
+		received += ret;
+	} while (ret);
+
+	if (received)
+		can_rx_fifo_schedule(fifo);
+
+	return received;
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_irq_offload_simple);
+
+static int can_rx_fifo_init_ring(struct net_device *dev,
+				 struct can_rx_fifo *fifo, unsigned int weight)
+{
+	fifo->dev = dev;
+
+	/* Make ring-buffer a sensible size that is a power of 2 */
+	fifo->ring_size = 2 << fls(weight);
+	fifo->ring = kzalloc(sizeof(struct can_frame) * fifo->ring_size,
+			     GFP_KERNEL);
+	if (!fifo->ring)
+		return -ENOMEM;
+
+	fifo->ring_head = fifo->ring_tail = 0;
+	netif_napi_add(dev, &fifo->napi, can_rx_fifo_napi_poll, weight);
+
+	return 0;
+}
+
+int can_rx_fifo_add_simple(struct net_device *dev, struct can_rx_fifo *fifo, unsigned int weight)
+{
+	int ret;
+
+	if (!fifo->mailbox_read)
+		return -EINVAL;
+
+	ret = can_rx_fifo_init_ring(dev, fifo, weight);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_add_simple);
+
+void can_rx_fifo_enable(struct can_rx_fifo *fifo)
+{
+	napi_enable(&fifo->napi);
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_enable);
+
+void can_rx_fifo_irq_error(struct can_rx_fifo *fifo)
+{
+	fifo->poll_errors = true;
+	can_rx_fifo_schedule(fifo);
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_irq_error);
+
+void can_rx_fifo_del(struct can_rx_fifo *fifo)
+{
+	netif_napi_del(&fifo->napi);
+	kfree(fifo->ring);
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_del);
diff --git a/include/linux/can/rx-fifo.h b/include/linux/can/rx-fifo.h
new file mode 100644
index 000000000000..fc157f23722c
--- /dev/null
+++ b/include/linux/can/rx-fifo.h
@@ -0,0 +1,58 @@
+/*
+ * linux/can/rx-fifo.h
+ *
+ * Copyright (c) 2014 David Jander, Protonic Holland
+ * Copyright (c) 2014, 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAN_RX_FIFO_H
+#define _CAN_RX_FIFO_H
+
+#include <linux/netdevice.h>
+#include <linux/can.h>
+
+struct can_rx_fifo {
+	struct net_device *dev;
+
+	void (*poll_error_interrupts_enable)(struct can_rx_fifo *fifo);
+	unsigned int (*mailbox_read)(struct can_rx_fifo *fifo, struct can_frame *cf, unsigned int mb);
+	unsigned int (*poll_pre_read)(struct can_rx_fifo *fifo);
+	unsigned int (*poll_post_read)(struct can_rx_fifo *fifo);
+
+	unsigned int ring_size;
+	unsigned int ring_head;
+	unsigned int ring_tail;
+
+	struct can_frame *ring;
+	struct can_frame overflow;
+	struct napi_struct napi;
+
+	bool poll_errors;
+};
+
+int can_rx_fifo_add_simple(struct net_device *dev, struct can_rx_fifo *fifo, unsigned int weight);
+int can_rx_fifo_irq_offload_simple(struct can_rx_fifo *fifo);
+void can_rx_fifo_irq_error(struct can_rx_fifo *fifo);
+void can_rx_fifo_del(struct can_rx_fifo *fifo);
+void can_rx_fifo_enable(struct can_rx_fifo *fifo);
+
+static inline void can_rx_fifo_schedule(struct can_rx_fifo *fifo)
+{
+	napi_schedule(&fifo->napi);
+}
+
+static inline void can_rx_fifo_disable(struct can_rx_fifo *fifo)
+{
+	napi_disable(&fifo->napi);
+}
+
+#endif /* !_CAN_RX_FIFO_H */
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 12/12] can: flexcan: make use of rx-fifos's irq_offload_simple
  2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2015-09-01  9:29 ` [PATCH 11/12] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
@ 2015-09-01  9:29 ` Marc Kleine-Budde
       [not found]   ` <CAOpc7mGfu7kT9qTNOC1P-_=7cRicscoLzqKpPE1kMx1HkueCwA@mail.gmail.com>
  11 siblings, 1 reply; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01  9:29 UTC (permalink / raw)
  Cc: linux-can, kernel, david, Marc Kleine-Budde

This patch converts the flexcan driver to make use of the rx-fifo
can_rx_fifo_irq_offload_simple() helper function. The idea is to read the CAN
frames already in the interrupt context, as the depth of the flexcan HW FIFO is
too shallow, resulting in too many missed frames. During a normal NAPI poll the
frames are the pushed into the upper layers.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 134 +++++++++++++++++++---------------------------
 1 file changed, 56 insertions(+), 78 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index a62bc43807c8..57eb6537799f 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -24,6 +24,7 @@
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 #include <linux/can/led.h>
+#include <linux/can/rx-fifo.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -246,13 +247,14 @@ struct flexcan_devtype_data {
 
 struct flexcan_priv {
 	struct can_priv can;
-	struct napi_struct napi;
+	struct can_rx_fifo fifo;
 
 	struct flexcan_regs __iomem *regs;
 	struct flexcan_mb __iomem *tx_mb;
 	struct flexcan_mb __iomem *tx_mb_reserved;
 	u8 tx_mb_idx;
 	u32 reg_esr;
+	u32 poll_esr;			/* used in flexcan_poll_bus_err */
 	u32 reg_ctrl_default;
 	u32 reg_imask1_default;
 
@@ -514,6 +516,11 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static inline struct flexcan_priv *rx_fifo_to_priv(struct can_rx_fifo *fifo)
+{
+	return container_of(fifo, struct flexcan_priv, fifo);
+}
+
 static void do_bus_err(struct net_device *dev,
 		       struct can_frame *cf, u32 reg_esr)
 {
@@ -562,16 +569,21 @@ static void do_bus_err(struct net_device *dev,
 		dev->stats.tx_errors++;
 }
 
-static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr)
+static unsigned int flexcan_poll_bus_err(struct can_rx_fifo *fifo)
 {
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
+	struct net_device *dev = fifo->dev;
 	struct sk_buff *skb;
 	struct can_frame *cf;
 
+	if (!flexcan_has_and_handle_berr(priv, priv->poll_esr))
+		return 0;
+
 	skb = alloc_can_err_skb(dev, &cf);
 	if (unlikely(!skb))
 		return 0;
 
-	do_bus_err(dev, cf, reg_esr);
+	do_bus_err(dev, cf, priv->poll_esr);
 
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += cf->can_dlc;
@@ -580,14 +592,21 @@ static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr)
 	return 1;
 }
 
-static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
+static unsigned int flexcan_poll_state(struct can_rx_fifo *fifo)
 {
-	struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
+	struct net_device *dev = fifo->dev;
+	struct flexcan_regs __iomem *regs = priv->regs;
 	struct sk_buff *skb;
 	struct can_frame *cf;
 	enum can_state new_state = 0, rx_state = 0, tx_state = 0;
 	int flt;
 	struct can_berr_counter bec;
+	u32 reg_esr;
+
+	/* esr bits are clear-on-read, so save them for flexcan_poll_bus_err() */
+	priv->poll_esr = priv->reg_esr | flexcan_read(&regs->esr);
+	reg_esr = priv->poll_esr;
 
 	flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
 	if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
@@ -624,13 +643,17 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
 	return 1;
 }
 
-static void flexcan_read_fifo(const struct net_device *dev,
-			      struct can_frame *cf)
+static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
+					 struct can_frame *cf, unsigned int n)
 {
-	const struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
 	struct flexcan_regs __iomem *regs = priv->regs;
-	struct flexcan_mb __iomem *mb = &regs->mb[0];
-	u32 reg_ctrl, reg_id;
+	struct flexcan_mb __iomem *mb = &regs->mb[n];
+	u32 reg_ctrl, reg_id, reg_iflag1;
+
+	reg_iflag1 = flexcan_read(&regs->iflag1);
+	if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE))
+		return 0;
 
 	reg_ctrl = flexcan_read(&mb->can_ctrl);
 	reg_id = flexcan_read(&mb->can_id);
@@ -649,67 +672,16 @@ static void flexcan_read_fifo(const struct net_device *dev,
 	/* mark as read */
 	flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
 	flexcan_read(&regs->timer);
-}
-
-static int flexcan_read_frame(struct net_device *dev)
-{
-	struct net_device_stats *stats = &dev->stats;
-	struct can_frame *cf;
-	struct sk_buff *skb;
-
-	skb = alloc_can_skb(dev, &cf);
-	if (unlikely(!skb)) {
-		stats->rx_dropped++;
-		return 0;
-	}
-
-	flexcan_read_fifo(dev, cf);
-
-	stats->rx_packets++;
-	stats->rx_bytes += cf->can_dlc;
-	netif_receive_skb(skb);
-
-	can_led_event(dev, CAN_LED_EVENT_RX);
 
 	return 1;
 }
 
-static int flexcan_poll(struct napi_struct *napi, int quota)
+static void flexcan_poll_error_interrupts_enable(struct can_rx_fifo *fifo)
 {
-	struct net_device *dev = napi->dev;
-	const struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
 	struct flexcan_regs __iomem *regs = priv->regs;
-	u32 reg_iflag1, reg_esr;
-	int work_done = 0;
-
-	/* The error bits are cleared on read,
-	 * use saved value from irq handler.
-	 */
-	reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
 
-	/* handle state changes */
-	work_done += flexcan_poll_state(dev, reg_esr);
-
-	/* handle RX-FIFO */
-	reg_iflag1 = flexcan_read(&regs->iflag1);
-	while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
-	       work_done < quota) {
-		work_done += flexcan_read_frame(dev);
-		reg_iflag1 = flexcan_read(&regs->iflag1);
-	}
-
-	/* report bus errors */
-	if (flexcan_has_and_handle_berr(priv, reg_esr) && work_done < quota)
-		work_done += flexcan_poll_bus_err(dev, reg_esr);
-
-	if (work_done < quota) {
-		napi_complete(napi);
-		/* enable IRQs */
-		flexcan_write(priv->reg_imask1_default, &regs->imask1);
-		flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
-	}
-
-	return work_done;
+	flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
 }
 
 static irqreturn_t flexcan_irq(int irq, void *dev_id)
@@ -727,25 +699,22 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	if (reg_esr & FLEXCAN_ESR_ALL_INT)
 		flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
 
-	/* schedule NAPI in case of:
-	 * - rx IRQ
-	 * - state change IRQ
-	 * - bus error IRQ and bus error reporting is activated
-	 */
-	if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) ||
-	    (reg_esr & FLEXCAN_ESR_ERR_STATE) ||
+	/* bus error IRQ and bus error reporting is activated */
+	if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
 	    flexcan_has_and_handle_berr(priv, reg_esr)) {
 		/* The error bits are cleared on read,
 		 * save them for later use.
 		 */
 		priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
-		flexcan_write(priv->reg_imask1_default &
-			      ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->imask1);
 		flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 			      &regs->ctrl);
-		napi_schedule(&priv->napi);
+		can_rx_fifo_irq_error(&priv->fifo);
 	}
 
+	/* reception interrupt */
+	if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE)
+		can_rx_fifo_irq_offload_simple(&priv->fifo);
+
 	/* FIFO overflow */
 	if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
 		flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
@@ -1008,7 +977,7 @@ static int flexcan_open(struct net_device *dev)
 
 	can_led_event(dev, CAN_LED_EVENT_OPEN);
 
-	napi_enable(&priv->napi);
+	can_rx_fifo_enable(&priv->fifo);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1030,7 +999,7 @@ static int flexcan_close(struct net_device *dev)
 	struct flexcan_priv *priv = netdev_priv(dev);
 
 	netif_stop_queue(dev);
-	napi_disable(&priv->napi);
+	can_rx_fifo_disable(&priv->fifo);
 	flexcan_chip_stop(dev);
 
 	free_irq(dev->irq, dev);
@@ -1235,7 +1204,15 @@ static int flexcan_probe(struct platform_device *pdev)
 		FLEXCAN_IFLAG_RX_FIFO_AVAILABLE |
 		FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
 
-	netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
+	priv->fifo.poll_pre_read = flexcan_poll_state;
+	priv->fifo.poll_post_read = flexcan_poll_bus_err;
+	priv->fifo.poll_error_interrupts_enable =
+		flexcan_poll_error_interrupts_enable;
+	priv->fifo.mailbox_read = flexcan_mailbox_read;
+
+	err = can_rx_fifo_add_simple(dev, &priv->fifo, FLEXCAN_NAPI_WEIGHT);
+	if (err)
+		goto failed_fifo;
 
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1253,6 +1230,7 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	return 0;
 
+ failed_fifo:
  failed_register:
 	free_candev(dev);
 	return err;
@@ -1264,7 +1242,7 @@ static int flexcan_remove(struct platform_device *pdev)
 	struct flexcan_priv *priv = netdev_priv(dev);
 
 	unregister_flexcandev(dev);
-	netif_napi_del(&priv->napi);
+	can_rx_fifo_del(&priv->fifo);
 	free_candev(dev);
 
 	return 0;
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 12/12] can: flexcan: make use of rx-fifos's irq_offload_simple
       [not found]   ` <CAOpc7mGfu7kT9qTNOC1P-_=7cRicscoLzqKpPE1kMx1HkueCwA@mail.gmail.com>
@ 2015-12-10 12:21     ` Marc Kleine-Budde
  0 siblings, 0 replies; 14+ messages in thread
From: Marc Kleine-Budde @ 2015-12-10 12:21 UTC (permalink / raw)
  To: Holger Schurig; +Cc: David Jander, Sascha Hauer, linux-can

[-- Attachment #1: Type: text/plain, Size: 458 bytes --]

On 12/09/2015 11:58 AM, Holger Schurig wrote:
> In case you submit this bug, change the subject "rx-fifos's" to
> "rx-fifo's". Two "s" is one too much :-)

Thx, fixed.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-12-10 12:21 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-01  9:29 [PATCH 00/12] RFC: cleanup flexcan driver, introduce and make use of IRQ offloading Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 01/12] can: headers: make header files self contained Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 02/12] can: flexcan: cleanup coding style and fix typos Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 03/12] can: flexcan: remove unused header files Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 04/12] can: flexcan: flexcan_chip_start(): cleanup writing of reg_mcr Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 05/12] can: flexcan: rename feature into quirks Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 06/12] can: flexcan: use pointer to struct regs instead of void pointer for mmio address space Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 07/12] can: flexcan: give member of flexcan_priv holding mailboxes a sensible name Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 08/12] can: flexcan: enable interrupts atomically at the end of flexcan_chip_start() Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 09/12] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 10/12] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 11/12] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
2015-09-01  9:29 ` [PATCH 12/12] can: flexcan: make use of rx-fifos's irq_offload_simple Marc Kleine-Budde
     [not found]   ` <CAOpc7mGfu7kT9qTNOC1P-_=7cRicscoLzqKpPE1kMx1HkueCwA@mail.gmail.com>
2015-12-10 12:21     ` Marc Kleine-Budde

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.