All of lore.kernel.org
 help / color / mirror / Atom feed
* rx-fifo: add implmentation and switch flexcan driver to use it
@ 2016-05-09 10:52 Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 01/10] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
                   ` (11 more replies)
  0 siblings, 12 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can

Hello,

this patch add support for a software bases rx-fifo implementation (patches
1+2). The remaining patches modify the flexcan driver to make use of it. imx6
and vf610 SoCs can make use of the 64 mailbox software FIFO, while older SoCs
still use flexcan's 6 mailbox deep hardware FIFO.

Testing on any flexcan core is highly appreciated.

regards,
Marc


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

* [PATCH 01/10] can: rx-fifo: Add support for simple irq offloading
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 02/10] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: David Jander, 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   | 174 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/can/rx-fifo.h |  58 +++++++++++++++
 3 files changed, 234 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 e3db0c807f55..9657d55ef03e 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..9ec8f99d8e2e
--- /dev/null
+++ b/drivers/net/can/rx-fifo.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014 David Jander, Protonic Holland
+ * Copyright (C) 2014-2016 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)
+{
+	if (!fifo->mailbox_read)
+		return -EINVAL;
+
+	return can_rx_fifo_init_ring(dev, fifo, weight);
+}
+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..0582564deaaf
--- /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-2016 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.8.1


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

* [PATCH 02/10] can: rx-fifo: introduce software rx-fifo implementation
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 01/10] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 03/10] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde, David Jander

This patch adds a software rx-fifo implementation for CAN controllers which
offer only a number of mailboxes, where the incoming message is stored into the
first free one. Both controllers which start with the lowest or highest free
mailbox are supported.

The mailboxes 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/rx-fifo.c   | 181 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/can/rx-fifo.h |  14 ++++
 2 files changed, 195 insertions(+)

diff --git a/drivers/net/can/rx-fifo.c b/drivers/net/can/rx-fifo.c
index 9ec8f99d8e2e..f72159bad7d3 100644
--- a/drivers/net/can/rx-fifo.c
+++ b/drivers/net/can/rx-fifo.c
@@ -19,6 +19,50 @@
 #include <linux/can/dev.h>
 #include <linux/can/rx-fifo.h>
 
+static bool can_rx_fifo_ge(struct can_rx_fifo *fifo, unsigned int a, unsigned int b)
+{
+	if (fifo->inc)
+		return a >= b;
+	else
+		return a <= b;
+}
+
+static bool can_rx_fifo_le(struct can_rx_fifo *fifo, unsigned int a, unsigned int b)
+{
+	if (fifo->inc)
+		return a <= b;
+	else
+		return a >= b;
+}
+
+static unsigned int can_rx_fifo_inc(struct can_rx_fifo *fifo, unsigned int *val)
+{
+	if (fifo->inc)
+		return (*val)++;
+	else
+		return (*val)--;
+}
+
+static u64 can_rx_fifo_mask_low(struct can_rx_fifo *fifo)
+{
+	if (fifo->inc)
+		return ~0LLU >> (64 + fifo->low_first - fifo->high_first)
+			     << fifo->low_first;
+	else
+		return ~0LLU >> (64 - fifo->low_first + fifo->high_first)
+			     << (fifo->high_first + 1);
+}
+
+static u64 can_rx_fifo_mask_high(struct can_rx_fifo *fifo)
+{
+	if (fifo->inc)
+		return ~0LLU >> (64 + fifo->high_first - fifo->high_last - 1)
+			     << fifo->high_first;
+	else
+		return ~0LLU >> (64 - fifo->high_first + fifo->high_last - 1)
+			     << fifo->high_last;
+}
+
 static int can_rx_fifo_napi_read_frame(struct can_rx_fifo *fifo, int index)
 {
 	struct net_device *dev = fifo->dev;
@@ -109,6 +153,71 @@ static unsigned int can_rx_fifo_offload_one(struct can_rx_fifo *fifo, unsigned i
 	return ret;
 }
 
+int can_rx_fifo_irq_offload(struct can_rx_fifo *fifo, u64 pending)
+{
+	unsigned int i;
+	unsigned int ret;
+	unsigned int received = 0;
+
+	if (fifo->scan_high_first) {
+		fifo->scan_high_first = false;
+		for (i = fifo->high_first;
+		     can_rx_fifo_le(fifo, i, fifo->high_last);
+		     can_rx_fifo_inc(fifo, &i)) {
+			if (pending & BIT_ULL(i)) {
+				received += can_rx_fifo_offload_one(fifo, i);
+
+				fifo->active |= BIT_ULL(i);
+				fifo->mailbox_enable(fifo, i);
+			}
+		}
+	}
+
+	/* Copy and disable FULL MBs */
+	for (i = fifo->low_first;
+	     can_rx_fifo_le(fifo, i, fifo->high_last);
+	     can_rx_fifo_inc(fifo, &i)) {
+		if (!(fifo->active & BIT_ULL(i) & pending))
+			continue;
+
+		ret = can_rx_fifo_offload_one(fifo, i);
+		if (!ret)
+			break;
+
+		received += ret;
+		fifo->active &= ~BIT_ULL(i);
+	}
+
+	if (can_rx_fifo_ge(fifo, i, fifo->high_first) && fifo->scan_high_first)
+		netdev_warn(fifo->dev, "%s: RX order cannot be guaranteed. (count=%d)\n",
+			    __func__, i);
+
+	/* No EMPTY MB in first half? */
+	if (can_rx_fifo_ge(fifo, i, fifo->high_first)) {
+		/* Re-enable all disabled MBs */
+		fifo->active = fifo->mask_low | fifo->mask_high;
+		fifo->mailbox_enable_mask(fifo, fifo->active);
+
+		/* Next time we need to check the second half first */
+		fifo->scan_high_first = true;
+	}
+
+	if (WARN(!received, "%s: No messages found, RX-FIFO out of sync?\n",
+		 __func__)) {
+		/* This should only happen if the CAN conroller was
+		 * reset, but can_rx_fifo_reset() was not
+		 * called. WARN() the user and try to recover. This
+		 * may fail and the system may hang though.
+		 */
+		can_rx_fifo_reset(fifo);
+	} else {
+		can_rx_fifo_schedule(fifo);
+	}
+
+	return received;
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_irq_offload);
+
 int can_rx_fifo_irq_offload_simple(struct can_rx_fifo *fifo)
 {
 	unsigned int received = 0;
@@ -139,11 +248,72 @@ static int can_rx_fifo_init_ring(struct net_device *dev,
 		return -ENOMEM;
 
 	fifo->ring_head = fifo->ring_tail = 0;
+	can_rx_fifo_reset(fifo);
 	netif_napi_add(dev, &fifo->napi, can_rx_fifo_napi_poll, weight);
 
 	return 0;
 }
 
+static void rx_fifo_enable_mask_default(struct can_rx_fifo *fifo, u64 mask)
+{
+	unsigned int i;
+
+	for (i = fifo->low_first;
+	     can_rx_fifo_le(fifo, i, fifo->high_last);
+	     can_rx_fifo_inc(fifo, &i)) {
+		if (mask & BIT_ULL(i))
+			fifo->mailbox_enable(fifo, i);
+	}
+}
+
+static void rx_fifo_enable_default(struct can_rx_fifo *fifo, unsigned int mb)
+{
+	fifo->mailbox_enable_mask(fifo, BIT_ULL(mb));
+}
+
+int can_rx_fifo_add(struct net_device *dev, struct can_rx_fifo *fifo)
+{
+	unsigned int weight;
+	int ret;
+
+	if ((fifo->low_first < fifo->high_first) &&
+	    (fifo->high_first < fifo->high_last)) {
+		fifo->inc = true;
+		weight = fifo->high_last - fifo->low_first;
+	} else if ((fifo->low_first > fifo->high_first) &&
+		   (fifo->high_first > fifo->high_last)) {
+		fifo->inc = false;
+		weight = fifo->low_first - fifo->high_last;
+	} else {
+		return -EINVAL;
+	}
+
+	if ((!fifo->mailbox_enable_mask && !fifo->mailbox_enable) ||
+	    !fifo->mailbox_read)
+		return -EINVAL;
+
+	if (!fifo->mailbox_enable_mask)
+		fifo->mailbox_enable_mask = rx_fifo_enable_mask_default;
+	if (!fifo->mailbox_enable)
+		fifo->mailbox_enable = rx_fifo_enable_default;
+
+	/* init variables */
+	fifo->mask_low = can_rx_fifo_mask_low(fifo);
+	fifo->mask_high = can_rx_fifo_mask_high(fifo);
+
+	ret = can_rx_fifo_init_ring(dev, fifo, weight);
+	if (ret)
+		return ret;
+
+	netdev_dbg(dev, "%s: low_first=%d, high_first=%d, high_last=%d\n", __func__,
+		   fifo->low_first, fifo->high_first, fifo->high_last);
+	netdev_dbg(dev, "%s: mask_low=0x%016llx mask_high=0x%016llx\n", __func__,
+		   fifo->mask_low, fifo->mask_high);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_add);
+
 int can_rx_fifo_add_simple(struct net_device *dev, struct can_rx_fifo *fifo, unsigned int weight)
 {
 	if (!fifo->mailbox_read)
@@ -155,6 +325,9 @@ EXPORT_SYMBOL_GPL(can_rx_fifo_add_simple);
 
 void can_rx_fifo_enable(struct can_rx_fifo *fifo)
 {
+	can_rx_fifo_reset(fifo);
+	if (fifo->mailbox_enable_mask)
+		fifo->mailbox_enable_mask(fifo, fifo->active);
 	napi_enable(&fifo->napi);
 }
 EXPORT_SYMBOL_GPL(can_rx_fifo_enable);
@@ -172,3 +345,11 @@ void can_rx_fifo_del(struct can_rx_fifo *fifo)
 	kfree(fifo->ring);
 }
 EXPORT_SYMBOL_GPL(can_rx_fifo_del);
+
+void can_rx_fifo_reset(struct can_rx_fifo *fifo)
+{
+	fifo->scan_high_first = false;
+	fifo->poll_errors = false;
+	fifo->active = fifo->mask_low | fifo->mask_high;
+}
+EXPORT_SYMBOL_GPL(can_rx_fifo_reset);
diff --git a/include/linux/can/rx-fifo.h b/include/linux/can/rx-fifo.h
index 0582564deaaf..6b19ae1584be 100644
--- a/include/linux/can/rx-fifo.h
+++ b/include/linux/can/rx-fifo.h
@@ -23,25 +23,39 @@
 struct can_rx_fifo {
 	struct net_device *dev;
 
+	void (*mailbox_enable_mask)(struct can_rx_fifo *fifo, u64 mask);
+	void (*mailbox_enable)(struct can_rx_fifo *fifo, unsigned int mb);
 	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);
 
+	u64 mask_low;
+	u64 mask_high;
+	u64 active;
+
 	unsigned int ring_size;
 	unsigned int ring_head;
 	unsigned int ring_tail;
+	unsigned int low_first;
+	unsigned int high_first;
+	unsigned int high_last;
 
 	struct can_frame *ring;
 	struct can_frame overflow;
 	struct napi_struct napi;
 
+	bool inc;
+	bool scan_high_first;
 	bool poll_errors;
 };
 
+int can_rx_fifo_add(struct net_device *dev, struct can_rx_fifo *fifo);
 int can_rx_fifo_add_simple(struct net_device *dev, struct can_rx_fifo *fifo, unsigned int weight);
+int can_rx_fifo_irq_offload(struct can_rx_fifo *fifo, u64 reg);
 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_reset(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);
 
-- 
2.8.1


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

* [PATCH 03/10] can: flexcan: calculate default value for imask1 during runtime
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 01/10] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 02/10] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 04/10] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: 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 41c0fc9f3b14..b377e1069bf8 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.8.1


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

* [PATCH 04/10] can: flexcan: make TX mailbox selectable during runtime
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 03/10] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple Marc Kleine-Budde
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: 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 b377e1069bf8..52065f2f92e0 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.8.1


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

* [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 04/10] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-20 11:31   ` Mirza Krak
  2016-05-09 10:52 ` [PATCH 06/10] can: flexcan: add missing register definitions Marc Kleine-Budde
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: 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 52065f2f92e0..bddd2ef904f0 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.8.1


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

* [PATCH 06/10] can: flexcan: add missing register definitions
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 07/10] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde

This patch adds some missing register definitions, which are needed in an
upcoming patch.

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

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index bddd2ef904f0..ef4693b970f4 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -56,7 +56,7 @@
 #define FLEXCAN_MCR_WAK_SRC		BIT(19)
 #define FLEXCAN_MCR_DOZE		BIT(18)
 #define FLEXCAN_MCR_SRX_DIS		BIT(17)
-#define FLEXCAN_MCR_BCC			BIT(16)
+#define FLEXCAN_MCR_IRMQ		BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
 #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
@@ -211,7 +211,10 @@ struct flexcan_regs {
 	u32 imask1;		/* 0x28 */
 	u32 iflag2;		/* 0x2c */
 	u32 iflag1;		/* 0x30 */
-	u32 ctrl2;		/* 0x34 */
+	union {			/* 0x34 */
+		u32 gfwr_mx28;	/* MX28, MX53 */
+		u32 ctrl2;	/* MX6, VF610 */
+	};
 	u32 esr2;		/* 0x38 */
 	u32 imeur;		/* 0x3c */
 	u32 lrfr;		/* 0x40 */
@@ -230,7 +233,11 @@ struct flexcan_regs {
 	 *				size conf'ed via ctrl2::RFFN
 	 *				(mx6, vf610)
 	 */
-	u32 _reserved4[408];
+	u32 _reserved4[256];	/* 0x480 */
+	u32 rximr[64];		/* 0x880 */
+	u32 _reserved5[24];	/* 0x980 */
+	u32 gfwr_mx6;		/* 0x9e0 - MX6 */
+	u32 _reserved6[63];	/* 0x9e4 */
 	u32 mecr;		/* 0xae0 */
 	u32 erriar;		/* 0xae4 */
 	u32 erridpr;		/* 0xae8 */
-- 
2.8.1


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

* [PATCH 07/10] can: flexcan: activate individual RX masking and initialize reg_rximr
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 06/10] can: flexcan: add missing register definitions Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 08/10] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde

Modern flexcan IP cores support two RX modes. One is using the 6 fames deep
hardware FIFO, the other is using up to 64 mailboxes (in non FIFO mode). For
now only the HW FIFO mode is activated.

In order to make use of the RX mailboxes the individual RX masking feature has
to be activated, otherwise matching mailboxes are overwritten during the
reception process. This however switches on the individual RX masking, which
uses reg_rximr registers for masking.

This patch activates the individual RX masking feature unconditionally and
initializes the mask registers (reg_rximr) with 0x0 == "don't care", which
switches off any filtering.

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

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index ef4693b970f4..f4c2bc4935a2 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -815,6 +815,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	 * only supervisor access
 	 * enable warning int
 	 * disable local echo
+	 * enable individual RX masking
 	 * choose format C
 	 * set max mailbox number
 	 */
@@ -822,7 +823,8 @@ 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(priv->tx_mb_idx);
+		FLEXCAN_MCR_IRMQ | 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);
 
@@ -881,6 +883,10 @@ static int flexcan_chip_start(struct net_device *dev)
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
 		flexcan_write(0x0, &regs->rxfgmask);
 
+	/* clear acceptance filters */
+	for (i = 0; i < ARRAY_SIZE(regs->mb); i++)
+		flexcan_write(0, &regs->rximr[i]);
+
 	/* On Vybrid, disable memory error detection interrupts
 	 * and freeze mode.
 	 * This also works around errata e5295 which generates
-- 
2.8.1


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

* [PATCH 08/10] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 07/10] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 09/10] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde

In order to receive RTR frames in the non HW FIFO mode the RSS and EACEN bits
of the reg_ctrl2 have to be activated. As this has no side effect in the FIFO
mode, we do this unconditionally on cores with the reg_ctrl2.

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

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index f4c2bc4935a2..b1135012ced3 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -187,7 +187,8 @@
  */
 #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 */
+#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS	BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
+#define FLEXCAN_QUIRK_DISABLE_MECR	BIT(4) /* Disble Memory error detection */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -279,11 +280,12 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG,
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS,
 };
 
 static struct flexcan_devtype_data fsl_vf610_devtype_data = {
-	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+		FLEXCAN_QUIRK_DISABLE_MECR,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -861,6 +863,12 @@ static int flexcan_chip_start(struct net_device *dev)
 	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
+	if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) {
+		reg_ctrl2 = flexcan_read(&regs->ctrl2);
+		reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS;
+		flexcan_write(reg_ctrl2, &regs->ctrl2);
+	}
+
 	/* clear and invalidate all mailboxes first */
 	for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) {
 		flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
-- 
2.8.1


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

* [PATCH 09/10] can: flexcan: add support for rx-fifo based software FIFO implementation
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 08/10] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:52 ` [PATCH 10/10] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde

The flexcan IP core has 64 mailboxes. For now they are configured for
RX as a hardware FIFO. This FIFO has a fixed depth of 6 CAN frames. In
some high load scenarios it turns out thas this buffer is too small.

In order to have a buffer larger than the 6 frames FIFO, this patch adds
support for a software based RX-FIFO bases on the generic rx-fifo
infrastructure.

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

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index b1135012ced3..9c7a9ce5b308 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 2005-2006 Varma Electronics Oy
  * Copyright (c) 2009 Sascha Hauer, Pengutronix
- * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
+ * Copyright (c) 2010-2016 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ * Copyright (c) 2014 David Jander, Protonic Holland
  *
  * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
  *
@@ -59,6 +60,7 @@
 #define FLEXCAN_MCR_IRMQ		BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
+/* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
 #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
 #define FLEXCAN_MCR_IDAM_A		(0x0 << 8)
 #define FLEXCAN_MCR_IDAM_B		(0x1 << 8)
@@ -146,12 +148,19 @@
 /* Errata ERR005829 step7: Reserve first valid MB */
 #define FLEXCAN_TX_MB_RESERVED_HW_FIFO	8
 #define FLEXCAN_TX_MB_HW_FIFO		9
+#define FLEXCAN_TX_MB_RESERVED_SW_FIFO	0
+#define FLEXCAN_TX_MB_SW_FIFO		1
+#define FLEXCAN_RX_MB_LOW_FIRST		(FLEXCAN_TX_MB_SW_FIFO + 1)
+#define FLEXCAN_RX_MB_HIGH_FIRST	32
+#define FLEXCAN_RX_MB_HIGH_LAST		63
 #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)
 
 /* FLEXCAN message buffers */
+#define FLEXCAN_MB_CODE_MASK		(0xf << 24)
+#define FLEXCAN_MB_CODE_RX_BUSY_BIT	(0x1 << 24)
 #define FLEXCAN_MB_CODE_RX_INACTIVE	(0x0 << 24)
 #define FLEXCAN_MB_CODE_RX_EMPTY	(0x4 << 24)
 #define FLEXCAN_MB_CODE_RX_FULL		(0x2 << 24)
@@ -189,6 +198,7 @@
 #define FLEXCAN_QUIRK_DISABLE_RXFG	BIT(2) /* Disable RX FIFO Global mask */
 #define FLEXCAN_QUIRK_ENABLE_EACEN_RRS	BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
 #define FLEXCAN_QUIRK_DISABLE_MECR	BIT(4) /* Disble Memory error detection */
+#define FLEXCAN_QUIRK_USE_SW_FIFO	BIT(5) /* Use SW-FIFO */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -265,6 +275,7 @@ struct flexcan_priv {
 	u32 poll_esr;			/* used in flexcan_poll_bus_err */
 	u32 reg_ctrl_default;
 	u32 reg_imask1_default;
+	u32 reg_imask2_default;
 
 	struct clk *clk_ipg;
 	struct clk *clk_per;
@@ -652,6 +663,49 @@ static unsigned int flexcan_poll_state(struct can_rx_fifo *fifo)
 	return 1;
 }
 
+static void do_mailbox_enable(struct flexcan_mb __iomem *mb)
+{
+	u32 reg_ctrl;
+	u32 code;
+
+	do {
+		reg_ctrl = flexcan_read(&mb->can_ctrl);
+	} while (reg_ctrl & FLEXCAN_MB_CODE_RX_BUSY_BIT);
+
+	code = reg_ctrl & FLEXCAN_MB_CODE_MASK;
+	if (code == FLEXCAN_MB_CODE_RX_INACTIVE) {
+		flexcan_write(FLEXCAN_MB_CODE_RX_EMPTY, &mb->can_ctrl);
+	}
+}
+
+static void flexcan_mailbox_enable(struct can_rx_fifo *fifo, unsigned int n)
+{
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
+	struct flexcan_regs __iomem *regs = priv->regs;
+
+	do_mailbox_enable(&regs->mb[n]);
+
+	/* unlock mailbox */
+	flexcan_read(&regs->timer);
+}
+
+static void flexcan_mailbox_enable_mask(struct can_rx_fifo *fifo, u64 mask)
+{
+	struct flexcan_priv *priv = rx_fifo_to_priv(fifo);
+	struct flexcan_regs __iomem *regs = priv->regs;
+	unsigned int i;
+
+	for (i = priv->fifo.low_first; i <= priv->fifo.high_last; i++) {
+		if (!(mask & BIT_ULL(i)))
+			continue;
+
+		do_mailbox_enable(&regs->mb[i]);
+	}
+
+	/* unlock mailbox */
+	flexcan_read(&regs->timer);
+}
+
 static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
 					 struct can_frame *cf, unsigned int n)
 {
@@ -660,11 +714,32 @@ static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
 	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;
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		u32 code;
+
+		do {
+			reg_ctrl = flexcan_read(&mb->can_ctrl);
+		} while (reg_ctrl & FLEXCAN_MB_CODE_RX_BUSY_BIT);
+
+		/* is this MB empty? */
+		code = reg_ctrl & FLEXCAN_MB_CODE_MASK;
+		if ((code != FLEXCAN_MB_CODE_RX_FULL) &&
+		    (code != FLEXCAN_MB_CODE_RX_OVERRUN))
+			return 0;
+
+		if (code == FLEXCAN_MB_CODE_RX_OVERRUN) {
+			/* This MB was overrun, we lost data */
+			fifo->dev->stats.rx_over_errors++;
+			fifo->dev->stats.rx_errors++;
+		}
+	} else {
+		reg_iflag1 = flexcan_read(&regs->iflag1);
+		if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE))
+			return 0;
+
+		reg_ctrl = flexcan_read(&mb->can_ctrl);
+	}
 
-	reg_ctrl = flexcan_read(&mb->can_ctrl);
 	reg_id = flexcan_read(&mb->can_id);
 	if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
 		cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
@@ -679,8 +754,18 @@ static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
 	*(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1]));
 
 	/* mark as read */
-	flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
-	flexcan_read(&regs->timer);
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		/* Clear IRQ and lock MB */
+		if (n < 32)
+			flexcan_write(BIT(n), &regs->iflag1);
+		else
+			flexcan_write(BIT(n - 32), &regs->iflag2);
+
+		flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, &mb->can_ctrl);
+	} else {
+		flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
+		flexcan_read(&regs->timer);
+	}
 
 	return 1;
 }
@@ -721,14 +806,27 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	}
 
 	/* reception interrupt */
-	if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE)
-		can_rx_fifo_irq_offload_simple(&priv->fifo);
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		u32 reg_iflag2;
+		u64 reg_iflag;
 
-	/* FIFO overflow */
-	if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
-		flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
-		dev->stats.rx_over_errors++;
-		dev->stats.rx_errors++;
+		reg_iflag2 = flexcan_read(&regs->iflag2);
+		reg_iflag = (reg_iflag1 & (priv->reg_imask1_default &
+					   ~FLEXCAN_IFLAG_MB(priv->tx_mb_idx))) |
+			((u64)(reg_iflag2 & priv->reg_imask2_default) << 32);
+
+		if (reg_iflag)
+			can_rx_fifo_irq_offload(&priv->fifo, reg_iflag);
+	} else {
+		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);
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+		}
 	}
 
 	/* transmission complete interrupt */
@@ -823,10 +921,17 @@ static int flexcan_chip_start(struct net_device *dev)
 	 */
 	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_SRX_DIS |
-		FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
-		FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
+		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		reg_mcr &= ~FLEXCAN_MCR_FEN;
+		reg_mcr |= FLEXCAN_MCR_MAXMB(priv->fifo.high_last);
+	} else {
+		reg_mcr |= FLEXCAN_MCR_FEN |
+			FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+	}
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	flexcan_write(reg_mcr, &regs->mcr);
 
@@ -875,6 +980,12 @@ static int flexcan_chip_start(struct net_device *dev)
 			      &regs->mb[i].can_ctrl);
 	}
 
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		for (i = priv->fifo.low_first; i <= priv->fifo.high_last; i++)
+			flexcan_write(FLEXCAN_MB_CODE_RX_EMPTY,
+				      &regs->mb[i].can_ctrl);
+	}
+
 	/* Errata ERR005829: mark first TX mailbox as INACTIVE */
 	flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
 		      &priv->tx_mb_reserved->can_ctrl);
@@ -933,6 +1044,7 @@ static int flexcan_chip_start(struct net_device *dev)
 	disable_irq(dev->irq);
 	flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
 	flexcan_write(priv->reg_imask1_default, &regs->imask1);
+	flexcan_write(priv->reg_imask2_default, &regs->imask2);
 	enable_irq(dev->irq);
 
 	/* print chip status */
@@ -962,6 +1074,7 @@ static void flexcan_chip_stop(struct net_device *dev)
 	flexcan_chip_disable(priv);
 
 	/* Disable all interrupts */
+	flexcan_write(0, &regs->imask2);
 	flexcan_write(0, &regs->imask1);
 	flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 		      &regs->ctrl);
@@ -1094,8 +1207,9 @@ static int register_flexcandev(struct net_device *dev)
 	flexcan_write(reg, &regs->mcr);
 
 	/* Currently we only support newer versions of this core
-	 * featuring a RX FIFO. Older cores found on some Coldfire
-	 * derivates are not yet supported.
+	 * featuring a RX hardware FIFO (although this driver doesn't
+	 * make use of it on some cores). Older cores, found on some
+	 * Coldfire derivates are not tested.
 	 */
 	reg = flexcan_read(&regs->mcr);
 	if (!(reg & FLEXCAN_MCR_FEN)) {
@@ -1217,13 +1331,17 @@ 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];
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		priv->tx_mb_idx = FLEXCAN_TX_MB_SW_FIFO;
+		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_SW_FIFO];
+	} else {
+		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_MB(priv->tx_mb_idx);
+	priv->reg_imask1_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+	priv->reg_imask2_default = 0;
 
 	priv->fifo.poll_pre_read = flexcan_poll_state;
 	priv->fifo.poll_post_read = flexcan_poll_bus_err;
@@ -1231,7 +1349,26 @@ static int flexcan_probe(struct platform_device *pdev)
 		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 (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+		u64 imask;
+
+		priv->fifo.low_first = FLEXCAN_RX_MB_LOW_FIRST;
+		priv->fifo.high_first = FLEXCAN_RX_MB_HIGH_FIRST;
+		priv->fifo.high_last = FLEXCAN_RX_MB_HIGH_LAST;
+		priv->fifo.mailbox_enable_mask = flexcan_mailbox_enable_mask;
+		priv->fifo.mailbox_enable = flexcan_mailbox_enable;
+
+		imask = ~0LLU >> (64 + priv->fifo.low_first - priv->fifo.high_last - 1)
+			      << priv->fifo.low_first;
+		priv->reg_imask1_default |= imask;
+		priv->reg_imask2_default |= imask >> 32;
+
+		err = can_rx_fifo_add(dev, &priv->fifo);
+	} else {
+		priv->reg_imask1_default |= FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
+			FLEXCAN_IFLAG_RX_FIFO_AVAILABLE;
+		err = can_rx_fifo_add_simple(dev, &priv->fifo, FLEXCAN_NAPI_WEIGHT);
+	}
 	if (err)
 		goto failed_fifo;
 
-- 
2.8.1


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

* [PATCH 10/10] can: flexcan: switch imx6 and vf610 to software based fifo
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 09/10] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
@ 2016-05-09 10:52 ` Marc Kleine-Budde
  2016-05-09 10:54 ` rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
  2016-05-10  8:27 ` Mirza Krak
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:52 UTC (permalink / raw)
  To: linux-can; +Cc: Marc Kleine-Budde

This patch switches the imx6 and vf610 based SoCs from the hardware to
the software based rx-fifo.

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

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 9c7a9ce5b308..24879a227781 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -291,12 +291,13 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS,
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+		FLEXCAN_QUIRK_USE_SW_FIFO,
 };
 
 static struct flexcan_devtype_data fsl_vf610_devtype_data = {
 	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
-		FLEXCAN_QUIRK_DISABLE_MECR,
+		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_SW_FIFO,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
-- 
2.8.1


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

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2016-05-09 10:52 ` [PATCH 10/10] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
@ 2016-05-09 10:54 ` Marc Kleine-Budde
  2016-05-10  8:27 ` Mirza Krak
  11 siblings, 0 replies; 18+ messages in thread
From: Marc Kleine-Budde @ 2016-05-09 10:54 UTC (permalink / raw)
  To: linux-can


[-- Attachment #1.1: Type: text/plain, Size: 833 bytes --]

On 05/09/2016 12:52 PM, Marc Kleine-Budde wrote:
> Hello,
> 
> this patch add support for a software bases rx-fifo implementation (patches
> 1+2). The remaining patches modify the flexcan driver to make use of it. imx6
> and vf610 SoCs can make use of the 64 mailbox software FIFO, while older SoCs
> still use flexcan's 6 mailbox deep hardware FIFO.
> 
> Testing on any flexcan core is highly appreciated.

BTW: This series is available on git:

https://git.kernel.org/cgit/linux/kernel/git/mkl/linux-can-next.git/log/?h=flexcan-next

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] 18+ messages in thread

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
  2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2016-05-09 10:54 ` rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
@ 2016-05-10  8:27 ` Mirza Krak
  2016-05-10 12:55   ` Mirza Krak
  11 siblings, 1 reply; 18+ messages in thread
From: Mirza Krak @ 2016-05-10  8:27 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can

2016-05-09 12:52 GMT+02:00 Marc Kleine-Budde <mkl@pengutronix.de>:
> Hello,
>
> this patch add support for a software bases rx-fifo implementation (patches
> 1+2). The remaining patches modify the flexcan driver to make use of it. imx6
> and vf610 SoCs can make use of the 64 mailbox software FIFO, while older SoCs
> still use flexcan's 6 mailbox deep hardware FIFO.
>
> Testing on any flexcan core is highly appreciated.

Hi Marc.

Tested your patch series on a vf610 SOC. I ran 2 x CAN @ 1Mbit, 80-90 % busload.

I do no longer get any "overrun" errors, which I got without your
patch series. And it seems to be stable, unlike previous patch series.
Improvement!

However I ran a simple sequence test and there seems to be some
ordering issues. I have some memory of that similar issues have been
discussed earlier on the mailing list and I am not quite sure if this
is related to your patch series but I get following:

root@mx4-v61-1000000:~/test/can_test# uname -a
Linux mx4-v61-1000000 4.1.15-00056-ge0b8ccc-dirty #12 Mon May 9
15:59:54 CEST 2016 armv7l GNU/Linux
root@mx4-v61-1000000:~/test/can_test# ./cansequence -r can1
interface = can1, family = 29, type = 3, proto = 1
received wrong sequence count. expected: 60, got: 61
received wrong sequence count. expected: 62, got: 60
received wrong sequence count. expected: 61, got: 62
received wrong sequence count. expected: 118, got: 119
received wrong sequence count. expected: 120, got: 118
received wrong sequence count. expected: 119, got: 120
received wrong sequence count. expected: 76, got: 77
received wrong sequence count. expected: 78, got: 76
received wrong sequence count. expected: 77, got: 78

One strange thing is that the sequence errors only occur on can1, can0
does not show any errors.

Otherwise statistics look good:
root@mx4-v61-1000000:~/test/can_test# ip -d -s link show can0
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state
UNKNOWN mode DEFAULT qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
    bitrate 1000000 sample-point 0.750
    tq 83 prop-seg 4 phase-seg1 4 phase-seg2 3 sjw 1
    flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
    clock 24000000
    re-started bus-errors arbit-lost error-warn error-pass bus-off
    0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    14000000   1750000  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    0          0        0       0       0       0
root@mx4-v61-1000000:~/test/can_test# ip -d -s link show can1
3: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state
UNKNOWN mode DEFAULT qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
    bitrate 1000000 sample-point 0.750
    tq 83 prop-seg 4 phase-seg1 4 phase-seg2 3 sjw 1
    flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
    clock 24000000
    re-started bus-errors arbit-lost error-warn error-pass bus-off
    0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    12000000   1500000  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    0          0        0       0       0       0

-- 
Med Vänliga Hälsningar / Best Regards

*******************************************************************
Mirza Krak
Host Mobility AB
mirza.krak@hostmobility.com
Anders Personsgatan 12, 416 64 Göteborg
Sweden
http://www.hostmobility.com
Direct: +46 31 31 32 704
Phone: +46 31 31 32 700
Fax: +46 31 80 67 51
Mobile: +46 730 28 06 22
*******************************************************************

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

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
  2016-05-10  8:27 ` Mirza Krak
@ 2016-05-10 12:55   ` Mirza Krak
  2016-05-11  9:12     ` Oliver Hartkopp
  0 siblings, 1 reply; 18+ messages in thread
From: Mirza Krak @ 2016-05-10 12:55 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can

2016-05-10 10:27 GMT+02:00 Mirza Krak <mirza.krak@hostmobility.com>:
> 2016-05-09 12:52 GMT+02:00 Marc Kleine-Budde <mkl@pengutronix.de>:
>> Hello,
>>
>> this patch add support for a software bases rx-fifo implementation (patches
>> 1+2). The remaining patches modify the flexcan driver to make use of it. imx6
>> and vf610 SoCs can make use of the 64 mailbox software FIFO, while older SoCs
>> still use flexcan's 6 mailbox deep hardware FIFO.
>>
>> Testing on any flexcan core is highly appreciated.
>
> Hi Marc.
>
> Tested your patch series on a vf610 SOC. I ran 2 x CAN @ 1Mbit, 80-90 % busload.
>
> I do no longer get any "overrun" errors, which I got without your
> patch series. And it seems to be stable, unlike previous patch series.
> Improvement!
>
> However I ran a simple sequence test and there seems to be some
> ordering issues. I have some memory of that similar issues have been
> discussed earlier on the mailing list and I am not quite sure if this
> is related to your patch series but I get following:
>
> root@mx4-v61-1000000:~/test/can_test# uname -a
> Linux mx4-v61-1000000 4.1.15-00056-ge0b8ccc-dirty #12 Mon May 9
> 15:59:54 CEST 2016 armv7l GNU/Linux
> root@mx4-v61-1000000:~/test/can_test# ./cansequence -r can1
> interface = can1, family = 29, type = 3, proto = 1
> received wrong sequence count. expected: 60, got: 61
> received wrong sequence count. expected: 62, got: 60
> received wrong sequence count. expected: 61, got: 62
> received wrong sequence count. expected: 118, got: 119
> received wrong sequence count. expected: 120, got: 118
> received wrong sequence count. expected: 119, got: 120
> received wrong sequence count. expected: 76, got: 77
> received wrong sequence count. expected: 78, got: 76
> received wrong sequence count. expected: 77, got: 78
>
> One strange thing is that the sequence errors only occur on can1, can0
> does not show any errors.

Some follow-up information.

Sequence errors occurs only if I run at 500 kbit/s or faster, which
suggests that higher CPU load triggers it.

I also ran same tests without your patch series and do not get any
sequence errors.

-- 
Med Vänliga Hälsningar / Best Regards

*******************************************************************
Mirza Krak
Host Mobility AB
mirza.krak@hostmobility.com
Anders Personsgatan 12, 416 64 Göteborg
Sweden
http://www.hostmobility.com
Direct: +46 31 31 32 704
Phone: +46 31 31 32 700
Fax: +46 31 80 67 51
Mobile: +46 730 28 06 22
*******************************************************************

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

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
  2016-05-10 12:55   ` Mirza Krak
@ 2016-05-11  9:12     ` Oliver Hartkopp
       [not found]       ` <CAJ=nTssNPDeGW+pEAHTpa+5ARQCQHfXumE=a=cr9prmjhgeJxQ@mail.gmail.com>
  2016-05-13 11:44       ` Tom Evans
  0 siblings, 2 replies; 18+ messages in thread
From: Oliver Hartkopp @ 2016-05-11  9:12 UTC (permalink / raw)
  To: Mirza Krak, Marc Kleine-Budde; +Cc: linux-can



On 05/10/2016 02:55 PM, Mirza Krak wrote:
> 2016-05-10 10:27 GMT+02:00 Mirza Krak <mirza.krak@hostmobility.com>:
>> 2016-05-09 12:52 GMT+02:00 Marc Kleine-Budde <mkl@pengutronix.de>:
>>> Hello,
>>>
>>> this patch add support for a software bases rx-fifo implementation (patches
>>> 1+2). The remaining patches modify the flexcan driver to make use of it. imx6
>>> and vf610 SoCs can make use of the 64 mailbox software FIFO, while older SoCs
>>> still use flexcan's 6 mailbox deep hardware FIFO.
>>>
>>> Testing on any flexcan core is highly appreciated.
>>
>> Hi Marc.
>>
>> Tested your patch series on a vf610 SOC. I ran 2 x CAN @ 1Mbit, 80-90 % busload.
>>
>> I do no longer get any "overrun" errors, which I got without your
>> patch series. And it seems to be stable, unlike previous patch series.
>> Improvement!
>>
>> However I ran a simple sequence test and there seems to be some
>> ordering issues. I have some memory of that similar issues have been
>> discussed earlier on the mailing list and I am not quite sure if this
>> is related to your patch series but I get following:
>>
>> root@mx4-v61-1000000:~/test/can_test# uname -a
>> Linux mx4-v61-1000000 4.1.15-00056-ge0b8ccc-dirty #12 Mon May 9
>> 15:59:54 CEST 2016 armv7l GNU/Linux
>> root@mx4-v61-1000000:~/test/can_test# ./cansequence -r can1
>> interface = can1, family = 29, type = 3, proto = 1
>> received wrong sequence count. expected: 60, got: 61
>> received wrong sequence count. expected: 62, got: 60
>> received wrong sequence count. expected: 61, got: 62
>> received wrong sequence count. expected: 118, got: 119
>> received wrong sequence count. expected: 120, got: 118
>> received wrong sequence count. expected: 119, got: 120
>> received wrong sequence count. expected: 76, got: 77
>> received wrong sequence count. expected: 78, got: 76
>> received wrong sequence count. expected: 77, got: 78
>>
>> One strange thing is that the sequence errors only occur on can1, can0
>> does not show any errors.

Hello Marc,

is it possible that the indirection irq -> rx-fifo -> napi can shuffle 
the CAN frames when the can1 irq is served by different CPUs?

We can probably set the processing CPU number into can_frame.__res0 for 
a test and print it in cansequence then.

Regards,
Oliver

ps. @Mirza: Thanks for testing!

>
> Some follow-up information.
>
> Sequence errors occurs only if I run at 500 kbit/s or faster, which
> suggests that higher CPU load triggers it.
>
> I also ran same tests without your patch series and do not get any
> sequence errors.
>

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

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
       [not found]       ` <CAJ=nTssNPDeGW+pEAHTpa+5ARQCQHfXumE=a=cr9prmjhgeJxQ@mail.gmail.com>
@ 2016-05-11 19:07         ` Mirza Krak
  0 siblings, 0 replies; 18+ messages in thread
From: Mirza Krak @ 2016-05-11 19:07 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: Marc Kleine-Budde, linux-can

Sorry, my phone e-mail client sent HTML formatted mail, which got
rejected. so re sending.

> Den 11 maj 2016 11:12 fm skrev "Oliver Hartkopp" <socketcan@hartkopp.net>:
>> Hello Marc,
>>
>> is it possible that the indirection irq -> rx-fifo -> napi can shuffle the
>> CAN frames when the can1 irq is served by different CPUs?

Should be noted that I ran my tests on a single core SOC.
-- 
Med Vänliga Hälsningar / Best Regards

*******************************************************************
Mirza Krak
Host Mobility AB
mirza.krak@hostmobility.com
Anders Personsgatan 12, 416 64 Göteborg
Sweden
http://www.hostmobility.com
Direct: +46 31 31 32 704
Phone: +46 31 31 32 700
Fax: +46 31 80 67 51
Mobile: +46 730 28 06 22
*******************************************************************

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

* Re: rx-fifo: add implmentation and switch flexcan driver to use it
  2016-05-11  9:12     ` Oliver Hartkopp
       [not found]       ` <CAJ=nTssNPDeGW+pEAHTpa+5ARQCQHfXumE=a=cr9prmjhgeJxQ@mail.gmail.com>
@ 2016-05-13 11:44       ` Tom Evans
  1 sibling, 0 replies; 18+ messages in thread
From: Tom Evans @ 2016-05-13 11:44 UTC (permalink / raw)
  To: Oliver Hartkopp, Mirza Krak, Marc Kleine-Budde; +Cc: linux-can

On 11/05/2016 7:12 PM, Oliver Hartkopp wrote:
>
>
> On 05/10/2016 02:55 PM, Mirza Krak wrote:
>> 2016-05-10 10:27 GMT+02:00 Mirza Krak <mirza.krak@hostmobility.com>:
>>> 2016-05-09 12:52 GMT+02:00 Marc Kleine-Budde <mkl@pengutronix.de>:
>>>> Hello,
>>>>
>>>> this patch add support for a software bases rx-fifo implementation 
>>>> (patches
>>>> 1+2). The remaining patches modify the flexcan driver to make use 
>>>> of it. imx6
>>>> and vf610 SoCs can make use of the 64 mailbox software FIFO, while 
>>>> older SoCs
>>>> still use flexcan's 6 mailbox deep hardware FIFO.
>>>>
>>>> Testing on any flexcan core is highly appreciated.
>>>
>>> Hi Marc.
>>>
>>> Tested your patch series on a vf610 SOC. I ran 2 x CAN @ 1Mbit, 
>>> 80-90 % busload.
>>>
>>> I do no longer get any "overrun" errors, which I got without your
>>> patch series. And it seems to be stable, unlike previous patch series.
>>> Improvement!
>>>
>>> However I ran a simple sequence test and there seems to be some
>>> ordering issues. I have some memory of that similar issues have been
>>> discussed earlier on the mailing list and I am not quite sure if this
>>> is related to your patch series but I get following:
>>>
>>> root@mx4-v61-1000000:~/test/can_test# uname -a
>>> Linux mx4-v61-1000000 4.1.15-00056-ge0b8ccc-dirty #12 Mon May 9
>>> 15:59:54 CEST 2016 armv7l GNU/Linux
>>> root@mx4-v61-1000000:~/test/can_test# ./cansequence -r can1
>>> interface = can1, family = 29, type = 3, proto = 1
>>> received wrong sequence count. expected: 60, got: 61
>>> received wrong sequence count. expected: 62, got: 60
>>> received wrong sequence count. expected: 61, got: 62
>>> received wrong sequence count. expected: 118, got: 119
>>> received wrong sequence count. expected: 120, got: 118
>>> received wrong sequence count. expected: 119, got: 120
>>> received wrong sequence count. expected: 76, got: 77
>>> received wrong sequence count. expected: 78, got: 76
>>> received wrong sequence count. expected: 77, got: 78
>>>
>>> One strange thing is that the sequence errors only occur on can1, can0
>>> does not show any errors.
>
> Hello Marc,
>
> is it possible that the indirection irq -> rx-fifo -> napi can shuffle 
> the CAN frames when the can1 irq is served by different CPUs?
>
> We can probably set the processing CPU number into can_frame.__res0 
> for a test and print it in cansequence then.
>
> Regards,
> Oliver
I've read through all the patches and can't work out how the code 
guarantees in-order reception. Freescale's original recommendation for 
using the MBs this way has always been to read them all, then SORT then 
based on the hardware timestamp to get them in order. They didn't do 
this in their Linux 2.6.35 driver and it certainly received out of order.

I've read through the patches and can't work out from there how 
reception order is guaranteed, but I have noticed the following can go 
wrong:

     netdev_warn(fifo->dev, "%s: RX order cannot be guaranteed.

Is there any background on the "software fifo" anywhere, or in any 
previous posts on the list I've missed?

Tom


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

* Re: [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple
  2016-05-09 10:52 ` [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple Marc Kleine-Budde
@ 2016-05-20 11:31   ` Mirza Krak
  0 siblings, 0 replies; 18+ messages in thread
From: Mirza Krak @ 2016-05-20 11:31 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Christian Magnusson

2016-05-09 12:52 GMT+02:00 Marc Kleine-Budde <mkl@pengutronix.de>:
>  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);
> +

Upon some further testing we noticed that upon "bus-errors" and
berr-reporting = on the controller never recovered.

If we get ONE bus-error, it will be set indefinitely and report a
ERRORFRAME on each received frame.

root@mx4-v61-1000000:/mnt/config# ./candump any,0:0,#FFFFFFFF
using interface name 'any'.
  can0  002   [1]  00
  can0  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME
  can1  002   [1]  00
  can1  002   [1]  01
  can1  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME
  can0  002   [1]  01
  can0  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME
  can1  002   [1]  02
  can1  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME
  can0  002   [1]  02
  can0  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME
  can0  002   [1]  03
  can0  20000088   [8]  00 00 04 00 00 00 00 00   ERRORFRAME

And the reson is because that the following code is not longer run on
a "reception interrupt".

>                 /* The error bits are cleared on read,
>                  * save them for later use.
>                  */
>                 priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;

Which means priv->reg_esr will never be cleared, and on each
flexcan_poll_state/flexcan_poll_bus_err call we will have a "error
bit" set and trigger ERRORFRAMES.

Thanks to Christian (on CC) who found this problem and proposed a solution.

One solution is to move "save of reg_esr" out from the condition and
do it regardless of what interrupt source triggered the interrupt.

Christian also suggested a solution of clearing "priv->reg_esr" in
flexcan_poll_state when are done with it.


-- 
Med Vänliga Hälsningar / Best Regards

*******************************************************************
Mirza Krak
Host Mobility AB
mirza.krak@hostmobility.com
Anders Personsgatan 12, 416 64 Göteborg
Sweden
http://www.hostmobility.com
Direct: +46 31 31 32 704
Phone: +46 31 31 32 700
Fax: +46 31 80 67 51
Mobile: +46 730 28 06 22
*******************************************************************

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

end of thread, other threads:[~2016-05-20 11:31 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-09 10:52 rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 01/10] can: rx-fifo: Add support for simple irq offloading Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 02/10] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 03/10] can: flexcan: calculate default value for imask1 during runtime Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 04/10] can: flexcan: make TX mailbox selectable " Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 05/10] can: flexcan: make use of rx-fifo's irq_offload_simple Marc Kleine-Budde
2016-05-20 11:31   ` Mirza Krak
2016-05-09 10:52 ` [PATCH 06/10] can: flexcan: add missing register definitions Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 07/10] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 08/10] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 09/10] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
2016-05-09 10:52 ` [PATCH 10/10] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
2016-05-09 10:54 ` rx-fifo: add implmentation and switch flexcan driver to use it Marc Kleine-Budde
2016-05-10  8:27 ` Mirza Krak
2016-05-10 12:55   ` Mirza Krak
2016-05-11  9:12     ` Oliver Hartkopp
     [not found]       ` <CAJ=nTssNPDeGW+pEAHTpa+5ARQCQHfXumE=a=cr9prmjhgeJxQ@mail.gmail.com>
2016-05-11 19:07         ` Mirza Krak
2016-05-13 11:44       ` Tom Evans

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.