* [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
@ 2015-09-01 10:31 Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 1/8] can: flexcan: add missing register definitions Marc Kleine-Budde
` (8 more replies)
0 siblings, 9 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david
Hello,
this series adds a software FIFO implementation and switches the flecan and
at91 driver to it. It's intended for CAN cores with a higher number of
mailboxes. The RX-FIFO is basically working, but on flexcan the WARN() in
can_rx_fifo_irq_offload() triggers. I'm currently debugging this issue.
This series depends on the earlier posted series "cleanup flexcan driver,
introduce and make use of IRQ offloading".
The git branch is available on:
https://git.kernel.org/cgit/linux/kernel/git/mkl/linux-can-next.git/log/?h=flexcan-next
git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git flexcan-next
Testing and feedback welcome, too.
regards,
Marc
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/8] can: flexcan: add missing register definitions
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
@ 2015-09-01 10:31 ` Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 2/8] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
` (7 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david, 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 57eb6537799f..457688f2929e 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.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/8] can: flexcan: activate individual RX masking and initialize reg_rximr
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 1/8] can: flexcan: add missing register definitions Marc Kleine-Budde
@ 2015-09-01 10:31 ` Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 3/8] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
` (6 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david, 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 457688f2929e..4c65a6795c77 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, ®s->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, ®s->rxfgmask);
+ /* clear acceptance filters */
+ for (i = 0; i < ARRAY_SIZE(regs->mb); i++)
+ flexcan_write(0, ®s->rximr[i]);
+
/* On Vybrid, disable memory error detection interrupts
* and freeze mode.
* This also works around errata e5295 which generates
--
2.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/8] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 1/8] can: flexcan: add missing register definitions Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 2/8] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
@ 2015-09-01 10:31 ` Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 4/8] can: flexcan: reg_imask2_default Marc Kleine-Budde
` (5 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david, 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 4c65a6795c77..1e213fd24e63 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, ®s->ctrl);
+ if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) {
+ reg_ctrl2 = flexcan_read(®s->ctrl2);
+ reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS;
+ flexcan_write(reg_ctrl2, ®s->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.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/8] can: flexcan: reg_imask2_default
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (2 preceding siblings ...)
2015-09-01 10:31 ` [PATCH 3/8] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
@ 2015-09-01 10:31 ` Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 5/8] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
` (4 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david, Marc Kleine-Budde
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/flexcan.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 1e213fd24e63..97e8d4581868 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -265,6 +265,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;
@@ -933,6 +934,7 @@ static int flexcan_chip_start(struct net_device *dev)
disable_irq(dev->irq);
flexcan_write(priv->reg_ctrl_default, ®s->ctrl);
flexcan_write(priv->reg_imask1_default, ®s->imask1);
+ flexcan_write(priv->reg_imask2_default, ®s->imask2);
enable_irq(dev->irq);
/* print chip status */
@@ -962,6 +964,7 @@ static void flexcan_chip_stop(struct net_device *dev)
flexcan_chip_disable(priv);
/* Disable all interrupts */
+ flexcan_write(0, ®s->imask2);
flexcan_write(0, ®s->imask1);
flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
®s->ctrl);
@@ -1224,6 +1227,7 @@ static int flexcan_probe(struct platform_device *pdev)
priv->reg_imask1_default = FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
FLEXCAN_IFLAG_RX_FIFO_AVAILABLE |
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;
--
2.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/8] can: rx-fifo: introduce software rx-fifo implementation
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (3 preceding siblings ...)
2015-09-01 10:31 ` [PATCH 4/8] can: flexcan: reg_imask2_default Marc Kleine-Budde
@ 2015-09-01 10:31 ` Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 6/8] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
` (3 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:31 UTC (permalink / raw)
Cc: linux-can, kernel, david, Marc Kleine-Budde
This patch adds a software rx-fifo implementation for CAN controllers which
offer only a number of mailboxes, where the incoming message is stored int othe
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 | 178 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/can/rx-fifo.h | 14 ++++
2 files changed, 192 insertions(+)
diff --git a/drivers/net/can/rx-fifo.c b/drivers/net/can/rx-fifo.c
index 2a0fb37f1bbb..57083fd483a3 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,68 @@ 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)
+{
+ 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)) {
+ 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)))
+ 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 +245,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)
{
int ret;
@@ -161,6 +328,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);
@@ -178,3 +348,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 fc157f23722c..cd1614118b33 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);
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.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/8] can: flexcan: add support for rx-fifo based software FIFO implementation
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (4 preceding siblings ...)
2015-09-01 10:31 ` [PATCH 5/8] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
@ 2015-09-01 10:32 ` Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 7/8] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
` (2 subsequent siblings)
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:32 UTC (permalink / raw)
Cc: linux-can, kernel, david, Marc Kleine-Budde
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/flexcan.c | 175 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 148 insertions(+), 27 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 97e8d4581868..415459030b60 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-2015 Marc Kleine-Budde, Pengutronix
+ * 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 {
@@ -653,6 +663,40 @@ static unsigned int flexcan_poll_state(struct can_rx_fifo *fifo)
return 1;
}
+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;
+ struct flexcan_mb __iomem *mb = ®s->mb[n];
+ u32 code;
+
+ code = flexcan_read(&mb->can_ctrl) & FLEXCAN_MB_CODE_MASK;
+ if (code == FLEXCAN_MB_CODE_RX_INACTIVE)
+ flexcan_write(FLEXCAN_MB_CODE_RX_EMPTY, &mb->can_ctrl);
+
+ flexcan_read(®s->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;
+ struct flexcan_mb __iomem *mb;
+ u32 code;
+ unsigned int i;
+
+ for (i = priv->fifo.low_first; i <= priv->fifo.high_last; i++) {
+ if (!(mask & BIT_ULL(i)))
+ continue;
+
+ mb = ®s->mb[i];
+ code = flexcan_read(&mb->can_ctrl) & FLEXCAN_MB_CODE_MASK;
+ if (code == FLEXCAN_MB_CODE_RX_INACTIVE)
+ flexcan_write(FLEXCAN_MB_CODE_RX_EMPTY, &mb->can_ctrl);
+ }
+ flexcan_read(®s->timer);
+}
+
static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
struct can_frame *cf, unsigned int n)
{
@@ -661,11 +705,32 @@ static unsigned int flexcan_mailbox_read(struct can_rx_fifo *fifo,
struct flexcan_mb __iomem *mb = ®s->mb[n];
u32 reg_ctrl, reg_id, reg_iflag1;
- reg_iflag1 = flexcan_read(®s->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(®s->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;
@@ -680,8 +745,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, ®s->iflag1);
- flexcan_read(®s->timer);
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+ /* Clear IRQ and lock MB */
+ if (n < 32)
+ flexcan_write(BIT(n), ®s->iflag1);
+ else
+ flexcan_write(BIT(n - 32), ®s->iflag2);
+
+ flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, &mb->can_ctrl);
+ } else {
+ flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1);
+ flexcan_read(®s->timer);
+ }
return 1;
}
@@ -722,14 +797,24 @@ 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);
-
- /* FIFO overflow */
- if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
- flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1);
- dev->stats.rx_over_errors++;
- dev->stats.rx_errors++;
+ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_SW_FIFO) {
+ u32 reg_iflag2;
+
+ reg_iflag2 = flexcan_read(®s->iflag2);
+ if (reg_iflag1 & (priv->reg_imask1_default &
+ ~FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) ||
+ reg_iflag2 & priv->reg_imask2_default)
+ can_rx_fifo_irq_offload(&priv->fifo);
+ } 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, ®s->iflag1);
+ dev->stats.rx_over_errors++;
+ dev->stats.rx_errors++;
+ }
}
/* transmission complete interrupt */
@@ -824,10 +909,17 @@ static int flexcan_chip_start(struct net_device *dev)
*/
reg_mcr = flexcan_read(®s->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, ®s->mcr);
@@ -876,6 +968,12 @@ static int flexcan_chip_start(struct net_device *dev)
®s->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,
+ ®s->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);
@@ -1097,8 +1195,9 @@ static int register_flexcandev(struct net_device *dev)
flexcan_write(reg, ®s->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(®s->mcr);
if (!(reg & FLEXCAN_MCR_FEN)) {
@@ -1220,13 +1319,16 @@ 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 = ®s->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 = ®s->mb[FLEXCAN_TX_MB_RESERVED_SW_FIFO];
+ } else {
+ priv->tx_mb_idx = FLEXCAN_TX_MB_HW_FIFO;
+ priv->tx_mb_reserved = ®s->mb[FLEXCAN_TX_MB_RESERVED_HW_FIFO];
+ }
priv->tx_mb = ®s->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;
@@ -1235,7 +1337,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.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 7/8] can: flexcan: switch imx6 and vf610 to software based fifo
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (5 preceding siblings ...)
2015-09-01 10:32 ` [PATCH 6/8] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
@ 2015-09-01 10:32 ` Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 8/8] can: at91_can: switch to rx-fifo implementation Marc Kleine-Budde
2015-09-02 23:58 ` [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Tom Evans
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:32 UTC (permalink / raw)
Cc: linux-can, kernel, david, Marc Kleine-Budde
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 415459030b60..50b15ef0ac4a 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.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 8/8] can: at91_can: switch to rx-fifo implementation
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (6 preceding siblings ...)
2015-09-01 10:32 ` [PATCH 7/8] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
@ 2015-09-01 10:32 ` Marc Kleine-Budde
2015-09-02 23:58 ` [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Tom Evans
8 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-01 10:32 UTC (permalink / raw)
Cc: linux-can, kernel, david, Marc Kleine-Budde
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/at91_can.c | 284 ++++++++++-----------------------------------
1 file changed, 64 insertions(+), 220 deletions(-)
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 945c0955a967..890bf6195c31 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -2,7 +2,7 @@
* at91_can.c - CAN network driver for AT91 SoC CAN controller
*
* (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
- * (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <kernel@pengutronix.de>
+ * (C) 2008-2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
*
* This software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2 as distributed in the 'COPYING'
@@ -38,6 +38,7 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
+#include <linux/can/rx-fifo.h>
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
@@ -138,14 +139,13 @@ struct at91_devtype_data {
struct at91_priv {
struct can_priv can; /* must be the first member! */
- struct napi_struct napi;
+ struct can_rx_fifo rx_fifo;
void __iomem *reg_base;
u32 reg_sr;
unsigned int tx_next;
unsigned int tx_echo;
- unsigned int rx_next;
struct at91_devtype_data devtype_data;
struct clk *clk;
@@ -154,6 +154,11 @@ struct at91_priv {
canid_t mb0_id;
};
+static inline struct at91_priv *rx_fifo_to_priv(struct can_rx_fifo *fifo)
+{
+ return container_of(fifo, struct at91_priv, rx_fifo);
+}
+
static const struct at91_devtype_data at91_at91sam9263_data = {
.rx_first = 1,
.rx_split = 8,
@@ -201,27 +206,11 @@ static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
return priv->devtype_data.rx_last;
}
-static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
-{
- return priv->devtype_data.rx_split;
-}
-
static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
{
return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
}
-static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
-{
- return get_mb_rx_split(priv) - 1;
-}
-
-static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
-{
- return AT91_MB_MASK(get_mb_rx_split(priv)) &
- ~AT91_MB_MASK(get_mb_rx_first(priv));
-}
-
static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
{
return priv->devtype_data.tx_shift;
@@ -367,9 +356,8 @@ static void at91_setup_mailboxes(struct net_device *dev)
for (i = get_mb_tx_first(priv); i <= get_mb_tx_last(priv); i++)
set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0);
- /* Reset tx and rx helper pointers */
+ /* Reset tx helper pointers */
priv->tx_next = priv->tx_echo = 0;
- priv->rx_next = get_mb_rx_first(priv);
}
static int at91_set_bittiming(struct net_device *dev)
@@ -428,6 +416,7 @@ static void at91_chip_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Enable interrupts */
+ can_rx_fifo_reset(&priv->rx_fifo);
reg_ier = get_irq_mb_rx(priv) | AT91_IRQ_ERRP | AT91_IRQ_ERR_FRAME;
at91_write(priv, AT91_IDR, AT91_IRQ_ALL);
at91_write(priv, AT91_IER, reg_ier);
@@ -532,32 +521,6 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/**
- * at91_activate_rx_low - activate lower rx mailboxes
- * @priv: a91 context
- *
- * Reenables the lower mailboxes for reception of new CAN messages
- */
-static inline void at91_activate_rx_low(const struct at91_priv *priv)
-{
- u32 mask = get_mb_rx_low_mask(priv);
- at91_write(priv, AT91_TCR, mask);
-}
-
-/**
- * at91_activate_rx_mb - reactive single rx mailbox
- * @priv: a91 context
- * @mb: mailbox to reactivate
- *
- * Reenables given mailbox for reception of new CAN messages
- */
-static inline void at91_activate_rx_mb(const struct at91_priv *priv,
- unsigned int mb)
-{
- u32 mask = 1 << mb;
- at91_write(priv, AT91_TCR, mask);
-}
-
-/**
* at91_rx_overflow_err - send error frame due to rx overflow
* @dev: net device
*/
@@ -580,33 +543,34 @@ static void at91_rx_overflow_err(struct net_device *dev)
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
- netif_receive_skb(skb);
+ netif_rx(skb);
}
/**
- * at91_read_mb - read CAN msg from mailbox (lowlevel impl)
- * @dev: net device
+ * at91_mailbox_read - read CAN msg from mailbox
+ * @fifo: rx-fifo
+ * @cf: CAN frame where to store message
* @mb: mailbox number to read from
- * @cf: can frame where to store message
*
* Reads a CAN message from the given mailbox and stores data into
- * given can frame. "mb" and "cf" must be valid.
+ * given can frame. "cf" and "mb" must be valid.
*/
-static void at91_read_mb(struct net_device *dev, unsigned int mb,
- struct can_frame *cf)
+static unsigned int at91_mailbox_read(struct can_rx_fifo *fifo, struct can_frame *cf, unsigned int mb)
{
- const struct at91_priv *priv = netdev_priv(dev);
+ const struct at91_priv *priv = rx_fifo_to_priv(fifo);
u32 reg_msr, reg_mid;
+ reg_msr = at91_read(priv, AT91_MSR(mb));
+ if (!(reg_msr & AT91_MSR_MRDY))
+ return 0;
+
reg_mid = at91_read(priv, AT91_MID(mb));
if (reg_mid & AT91_MID_MIDE)
cf->can_id = ((reg_mid >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
else
cf->can_id = (reg_mid >> 18) & CAN_SFF_MASK;
- reg_msr = at91_read(priv, AT91_MSR(mb));
cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
-
if (reg_msr & AT91_MSR_MRTR)
cf->can_id |= CAN_RTR_FLAG;
else {
@@ -618,127 +582,20 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
at91_write(priv, AT91_MID(mb), AT91_MID_MIDE);
if (unlikely(mb == get_mb_rx_last(priv) && reg_msr & AT91_MSR_MMI))
- at91_rx_overflow_err(dev);
-}
-
-/**
- * at91_read_msg - read CAN message from mailbox
- * @dev: net device
- * @mb: mail box to read from
- *
- * Reads a CAN message from given mailbox, and put into linux network
- * RX queue, does all housekeeping chores (stats, ...)
- */
-static void at91_read_msg(struct net_device *dev, unsigned int mb)
-{
- 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;
- }
-
- at91_read_mb(dev, mb, cf);
+ at91_rx_overflow_err(fifo->dev);
- stats->rx_packets++;
- stats->rx_bytes += cf->can_dlc;
- netif_receive_skb(skb);
+ /* disable MB for now */
+ at91_write(priv, AT91_IDR, 1 << mb);
- can_led_event(dev, CAN_LED_EVENT_RX);
+ return 1;
}
-/**
- * at91_poll_rx - read multiple CAN messages from mailboxes
- * @dev: net device
- * @quota: max number of pkgs we're allowed to receive
- *
- * Theory of Operation:
- *
- * About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
- * on the chip are reserved for RX. We split them into 2 groups. The
- * lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
- *
- * Like it or not, but the chip always saves a received CAN message
- * into the first free mailbox it finds (starting with the
- * lowest). This makes it very difficult to read the messages in the
- * right order from the chip. This is how we work around that problem:
- *
- * The first message goes into mb nr. 1 and issues an interrupt. All
- * rx ints are disabled in the interrupt handler and a napi poll is
- * scheduled. We read the mailbox, but do _not_ reenable the mb (to
- * receive another message).
- *
- * lower mbxs upper
- * ____^______ __^__
- * / \ / \
- * +-+-+-+-+-+-+-+-++-+-+-+-+
- * | |x|x|x|x|x|x|x|| | | | |
- * +-+-+-+-+-+-+-+-++-+-+-+-+
- * 0 0 0 0 0 0 0 0 0 0 1 1 \ mail
- * 0 1 2 3 4 5 6 7 8 9 0 1 / box
- * ^
- * |
- * \
- * unused, due to chip bug
- *
- * The variable priv->rx_next points to the next mailbox to read a
- * message from. As long we're in the lower mailboxes we just read the
- * mailbox but not reenable it.
- *
- * With completion of the last of the lower mailboxes, we reenable the
- * whole first group, but continue to look for filled mailboxes in the
- * upper mailboxes. Imagine the second group like overflow mailboxes,
- * which takes CAN messages if the lower goup is full. While in the
- * upper group we reenable the mailbox right after reading it. Giving
- * the chip more room to store messages.
- *
- * After finishing we look again in the lower group if we've still
- * quota.
- *
- */
-static int at91_poll_rx(struct net_device *dev, int quota)
+static void at91_mailbox_enable_mask(struct can_rx_fifo *fifo, u64 mask)
{
- struct at91_priv *priv = netdev_priv(dev);
- u32 reg_sr = at91_read(priv, AT91_SR);
- const unsigned long *addr = (unsigned long *)®_sr;
- unsigned int mb;
- int received = 0;
-
- if (priv->rx_next > get_mb_rx_low_last(priv) &&
- reg_sr & get_mb_rx_low_mask(priv))
- netdev_info(dev,
- "order of incoming frames cannot be guaranteed\n");
-
- again:
- for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
- mb < get_mb_tx_first(priv) && quota > 0;
- reg_sr = at91_read(priv, AT91_SR),
- mb = find_next_bit(addr, get_mb_tx_first(priv), ++priv->rx_next)) {
- at91_read_msg(dev, mb);
-
- /* reactivate mailboxes */
- if (mb == get_mb_rx_low_last(priv))
- /* all lower mailboxed, if just finished it */
- at91_activate_rx_low(priv);
- else if (mb > get_mb_rx_low_last(priv))
- /* only the mailbox we read */
- at91_activate_rx_mb(priv, mb);
-
- received++;
- quota--;
- }
-
- /* upper group completed, look again in lower */
- if (priv->rx_next > get_mb_rx_low_last(priv) &&
- quota > 0 && mb > get_mb_rx_last(priv)) {
- priv->rx_next = get_mb_rx_first(priv);
- goto again;
- }
+ struct at91_priv *priv = rx_fifo_to_priv(fifo);
- return received;
+ at91_write(priv, AT91_TCR, mask);
+ at91_write(priv, AT91_IER, mask);
}
static void at91_poll_err_frame(struct net_device *dev,
@@ -789,12 +646,16 @@ static void at91_poll_err_frame(struct net_device *dev,
}
}
-static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
+static unsigned int at91_poll_err(struct can_rx_fifo *fifo)
{
+ struct at91_priv *priv = rx_fifo_to_priv(fifo);
+ struct net_device *dev = fifo->dev;
struct sk_buff *skb;
struct can_frame *cf;
+ u32 reg_sr;
- if (quota == 0)
+ reg_sr = priv->reg_sr;
+ if (!(reg_sr & AT91_IRQ_ERR_FRAME))
return 0;
skb = alloc_can_err_skb(dev, &cf);
@@ -802,6 +663,7 @@ static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
return 0;
at91_poll_err_frame(dev, cf, reg_sr);
+ priv->reg_sr = 0;
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
@@ -810,34 +672,11 @@ static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
return 1;
}
-static int at91_poll(struct napi_struct *napi, int quota)
+static void at91_poll_error_interrupts_enable(struct can_rx_fifo *fifo)
{
- struct net_device *dev = napi->dev;
- const struct at91_priv *priv = netdev_priv(dev);
- u32 reg_sr = at91_read(priv, AT91_SR);
- int work_done = 0;
-
- if (reg_sr & get_irq_mb_rx(priv))
- work_done += at91_poll_rx(dev, quota - work_done);
-
- /*
- * The error bits are clear on read,
- * so use saved value from irq handler.
- */
- reg_sr |= priv->reg_sr;
- if (reg_sr & AT91_IRQ_ERR_FRAME)
- work_done += at91_poll_err(dev, quota - work_done, reg_sr);
-
- if (work_done < quota) {
- /* enable IRQs for frame errors and all mailboxes >= rx_next */
- u32 reg_ier = AT91_IRQ_ERR_FRAME;
- reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
+ struct at91_priv *priv = rx_fifo_to_priv(fifo);
- napi_complete(napi);
- at91_write(priv, AT91_IER, reg_ier);
- }
-
- return work_done;
+ at91_write(priv, AT91_IER, AT91_IRQ_ERR_FRAME);
}
/*
@@ -958,7 +797,6 @@ static void at91_irq_err_state(struct net_device *dev,
break;
}
-
/* process state changes depending on the new state */
switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
@@ -1026,7 +864,6 @@ static int at91_get_state_by_bec(const struct net_device *dev,
return 0;
}
-
static void at91_irq_err(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@@ -1049,7 +886,7 @@ static void at91_irq_err(struct net_device *dev)
else if (likely(reg_sr & AT91_IRQ_ERRA))
new_state = CAN_STATE_ERROR_ACTIVE;
else {
- netdev_err(dev, "BUG! hardware in undefined state\n");
+ netdev_err(dev, "BUG! hardware in undefined state (reg_sr=0x%08x)\n", reg_sr);
return;
}
} else {
@@ -1082,7 +919,6 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct at91_priv *priv = netdev_priv(dev);
- irqreturn_t handled = IRQ_NONE;
u32 reg_sr, reg_imr;
reg_sr = at91_read(priv, AT91_SR);
@@ -1091,30 +927,30 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
/* Ignore masked interrupts */
reg_sr &= reg_imr;
if (!reg_sr)
- goto exit;
-
- handled = IRQ_HANDLED;
+ return IRQ_NONE;
- /* Receive or error interrupt? -> napi */
- if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
- /*
- * The error bits are clear on read,
+ /* Error interrupt? -> rx-fifo */
+ if (reg_sr & AT91_IRQ_ERR_FRAME) {
+ /* The error bits are clear on read,
* save for later use.
*/
priv->reg_sr = reg_sr;
- at91_write(priv, AT91_IDR,
- get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME);
- napi_schedule(&priv->napi);
+
+ at91_write(priv, AT91_IDR, AT91_IRQ_ERR_FRAME);
+ can_rx_fifo_irq_error(&priv->rx_fifo);
}
+ /* Receive interrupt? */
+ if (reg_sr & (get_irq_mb_rx(priv)))
+ can_rx_fifo_irq_offload(&priv->rx_fifo);
+
/* Transmission complete interrupt */
if (reg_sr & get_irq_mb_tx(priv))
at91_irq_tx(dev, reg_sr);
at91_irq_err(dev);
- exit:
- return handled;
+ return IRQ_HANDLED;
}
static int at91_open(struct net_device *dev)
@@ -1142,7 +978,7 @@ static int at91_open(struct net_device *dev)
/* start chip and queuing */
at91_chip_start(dev);
- napi_enable(&priv->napi);
+ can_rx_fifo_enable(&priv->rx_fifo);
netif_start_queue(dev);
return 0;
@@ -1163,7 +999,7 @@ static int at91_close(struct net_device *dev)
struct at91_priv *priv = netdev_priv(dev);
netif_stop_queue(dev);
- napi_disable(&priv->napi);
+ can_rx_fifo_disable(&priv->rx_fifo);
at91_chip_stop(dev, CAN_STATE_STOPPED);
free_irq(dev->irq, dev);
@@ -1354,8 +1190,16 @@ static int at91_can_probe(struct platform_device *pdev)
priv->clk = clk;
priv->pdata = dev_get_platdata(&pdev->dev);
priv->mb0_id = 0x7ff;
-
- netif_napi_add(dev, &priv->napi, at91_poll, get_mb_rx_num(priv));
+ priv->rx_fifo.low_first = devtype_data->rx_first;
+ priv->rx_fifo.high_first = devtype_data->rx_split;
+ priv->rx_fifo.high_last = devtype_data->rx_last;
+ priv->rx_fifo.poll_post_read = at91_poll_err;
+ priv->rx_fifo.poll_error_interrupts_enable =
+ at91_poll_error_interrupts_enable;
+ priv->rx_fifo.mailbox_enable_mask = at91_mailbox_enable_mask;
+ priv->rx_fifo.mailbox_read = at91_mailbox_read;
+
+ can_rx_fifo_add(dev, &priv->rx_fifo);
if (at91_is_sam9263(priv))
dev->sysfs_groups[0] = &at91_sysfs_attr_group;
--
2.5.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
` (7 preceding siblings ...)
2015-09-01 10:32 ` [PATCH 8/8] can: at91_can: switch to rx-fifo implementation Marc Kleine-Budde
@ 2015-09-02 23:58 ` Tom Evans
2015-09-03 6:32 ` David Jander
8 siblings, 1 reply; 17+ messages in thread
From: Tom Evans @ 2015-09-02 23:58 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: linux-can, kernel, david
On 01/09/15 20:31, Marc Kleine-Budde wrote:
> Hello,
>
> this series adds a software FIFO implementation and switches
> the flecan and at91 driver to it. It's intended for CAN cores
> with a higher number of mailboxes.
It is a bit difficult to understand the changed by looking at 20 patches, so
I'm assuming this is the change where what the i.MX6 manuals calls the
"Reception Queue" mode is enabled.
I see "[PATCH 1/8]" renaming "FLEXCAN_MCR_BCC" to "FLEXCAN_MCR_IRMQ" and
"[PATCH 2/8]" adding it to the MCR setting.
Use of the "Reception Queue" is documented in the i.MX6DQ manual in section
"26.6.5 Matching Process" as:
By programming more than one MB with the same ID, received
messages will be queued into the MBs. ARM can examine the
Time Stamp field of the MBs to determine the order in which
the messages arrived.
Is the new code sorting the messages by using the timestamp, or have you found
another way to guarantee reception order?
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-02 23:58 ` [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Tom Evans
@ 2015-09-03 6:32 ` David Jander
2015-09-03 6:58 ` Marc Kleine-Budde
0 siblings, 1 reply; 17+ messages in thread
From: David Jander @ 2015-09-03 6:32 UTC (permalink / raw)
To: Tom Evans; +Cc: Marc Kleine-Budde, linux-can, kernel
Dear Tom,
On Thu, 3 Sep 2015 09:58:58 +1000
Tom Evans <tom_usenet@optusnet.com.au> wrote:
> On 01/09/15 20:31, Marc Kleine-Budde wrote:
> > Hello,
> >
> > this series adds a software FIFO implementation and switches
> > the flecan and at91 driver to it. It's intended for CAN cores
> > with a higher number of mailboxes.
>
> It is a bit difficult to understand the changed by looking at 20 patches, so
> I'm assuming this is the change where what the i.MX6 manuals calls the
> "Reception Queue" mode is enabled.
>
> I see "[PATCH 1/8]" renaming "FLEXCAN_MCR_BCC" to "FLEXCAN_MCR_IRMQ" and
> "[PATCH 2/8]" adding it to the MCR setting.
>
> Use of the "Reception Queue" is documented in the i.MX6DQ manual in section
> "26.6.5 Matching Process" as:
>
> By programming more than one MB with the same ID, received
> messages will be queued into the MBs. ARM can examine the
> Time Stamp field of the MBs to determine the order in which
> the messages arrived.
>
> Is the new code sorting the messages by using the timestamp, or have you
> found another way to guarantee reception order?
Almost. Generic code in can/dev.c cannot know about special features like
timestamps that some peripherals may provide. There is another way to
guarantee the reception order which is more generic, and is inspired by how
the at91can driver did things before this patch. It basically works like this:
The MB area is divided into two halves. For simplicity, we will assume that
your can controller (like flexcan) starts filling MB's from the lowest free MB
upwards. This can be the other way around for other controllers though.
In the RX interrupt we simply read out all MB's from the beginning that have
new messages (we keep track of where we were last time). In an atomic
operation, the MB's that have been served are now disabled. Once we reach the
second half of our MB space, all disabled MB's from the first half are enabled
again. The next time we hit the RX interrupt we first check if there are more
messages in the second half and handle those first and then start over again
from the bottom.
If there are pending MB's (with messages to be read) in the first MB and also
in the second half, we know there is an overflow. We still have all messages
but we cannot guarantee the ordering anymore. Therefor the lower half needs to
be big enough. Fortunately the flexcan controller has quite a big MB area
compared to its hardware FIFO, which is much smaller, so overall the
reliability of the driver is greatly improved. Not to mention the fact that
MB's are now also cleared in the hard-IRQ, which further reduces latency.
Best regards,
--
David Jander
Protonic Holland.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 6:32 ` David Jander
@ 2015-09-03 6:58 ` Marc Kleine-Budde
2015-09-03 8:17 ` Tom Evans
0 siblings, 1 reply; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-03 6:58 UTC (permalink / raw)
To: David Jander, Tom Evans; +Cc: linux-can, kernel
[-- Attachment #1: Type: text/plain, Size: 2110 bytes --]
On 09/03/2015 08:32 AM, David Jander wrote:
>>> this series adds a software FIFO implementation and switches
>> > the flecan and at91 driver to it. It's intended for CAN cores
>> > with a higher number of mailboxes.
>>
>> It is a bit difficult to understand the changed by looking at 20 patches, so
>> I'm assuming this is the change where what the i.MX6 manuals calls the
>> "Reception Queue" mode is enabled.
In the first series the "real" change happens at Patch 12/12. The
hardware FIFO which was handled in NAPI now it's handled in a hard IRQ
context. It's making use of the code introduced in patch 11/12.
>> I see "[PATCH 1/8]" renaming "FLEXCAN_MCR_BCC" to "FLEXCAN_MCR_IRMQ" and
>> "[PATCH 2/8]" adding it to the MCR setting.
These are just preparation patches. But you're right, the MCR_IRMQ is
essential for software FIFO.
>> Use of the "Reception Queue" is documented in the i.MX6DQ manual in section
>> "26.6.5 Matching Process" as:
>>
>> By programming more than one MB with the same ID, received
>> messages will be queued into the MBs. ARM can examine the
>> Time Stamp field of the MBs to determine the order in which
>> the messages arrived.
>>
>> Is the new code sorting the messages by using the timestamp, or have you
>> found another way to guarantee reception order?
>
> Almost. Generic code in can/dev.c cannot know about special features like
> timestamps that some peripherals may provide.
Thanks to David explaining the algorithm.
The generic code is added in 5/8, the flexcan specific code is added in 7/8.
Regarding the time stamp feature. IIRC, the mailboxes in the AT91 have
timestamps, too. When the generic SW-FIFO code is stable and someone is
interested, sorting by timestamps can be added to the generic code base.
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] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 6:58 ` Marc Kleine-Budde
@ 2015-09-03 8:17 ` Tom Evans
2015-09-03 8:38 ` David Jander
2015-09-03 8:45 ` Marc Kleine-Budde
0 siblings, 2 replies; 17+ messages in thread
From: Tom Evans @ 2015-09-03 8:17 UTC (permalink / raw)
To: Marc Kleine-Budde, David Jander; +Cc: linux-can, kernel
On 03/09/15 16:58, Marc Kleine-Budde wrote:
> On 09/03/2015 08:32 AM, David Jander wrote:
>>>> this series adds a software FIFO implementation and switches
Thank you both for explaining that.
It seems fairly bulletproof as long as it doesn't overflow. There are 64
buffers, so 32 in the first half, so that handles a 1.5ms interrupt latency.
A shame Freescale didn't think of that method instead of requiring the driver
run quicksort somewhere.
> In an atomic operation, the MB's that have been served are
> now disabled.
That's the sort of tricky operation that exposes nasty silicon bugs. I'd
suggest that this mode be made easy to turn off in case some chip variant has
a problem like htis.
This feature looks to be enabled as a "QUIRK" of the CPU.
In an old generation kernel this might be optionally enabled in the .config
file, as NAPI is in the 2.6.35 FEC drivers I'm stuck with using at the moment
on the i.MX53. In the current kernel, could this mode of operation (and/or
hardware FIFO using NAPI) be made configurable in the Device Tree instead?
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 8:17 ` Tom Evans
@ 2015-09-03 8:38 ` David Jander
2015-09-03 8:47 ` Marc Kleine-Budde
2015-09-04 3:19 ` Tom Evans
2015-09-03 8:45 ` Marc Kleine-Budde
1 sibling, 2 replies; 17+ messages in thread
From: David Jander @ 2015-09-03 8:38 UTC (permalink / raw)
To: Tom Evans; +Cc: Marc Kleine-Budde, linux-can, kernel
On Thu, 3 Sep 2015 18:17:53 +1000
Tom Evans <tom_usenet@optusnet.com.au> wrote:
> On 03/09/15 16:58, Marc Kleine-Budde wrote:
> > On 09/03/2015 08:32 AM, David Jander wrote:
> >>>> this series adds a software FIFO implementation and switches
>
> Thank you both for explaining that.
>
> It seems fairly bulletproof as long as it doesn't overflow. There are 64
> buffers, so 32 in the first half, so that handles a 1.5ms interrupt latency.
>
> A shame Freescale didn't think of that method instead of requiring the
> driver run quicksort somewhere.
>
> > In an atomic operation, the MB's that have been served are
> > now disabled.
>
> That's the sort of tricky operation that exposes nasty silicon bugs. I'd
> suggest that this mode be made easy to turn off in case some chip variant
> has a problem like htis.
The use of RX-FIFO, either the simple IRQ off-load or full implementation for
linear MB areas is selectable and optional. Each driver can choose to use the
mechanism most suited for it. If there are silicon-bugs, the necessary
run-time detection in the driver should choose to use or not to use either.
> This feature looks to be enabled as a "QUIRK" of the CPU.
Not really. The problem with flexcan specifically is that the flexcan cores
prior to revision 10 are not able to receive RTR messages in the MB area, so
using the full implementation of RX-FIFO in that case would break RTR
reception. That's the reason why for V10 and newer flexcan cores we use the
full implementation, while for older ones, the simple IRQ off-load method is
used, retaining the hardware FIFO functionality of the peripheral.
The fact that these "FEATURE" bits where all renamed to be "QUIRK"s is 75%
better than before, but in this case (the other 25%) the name "FEATURE" would
be more fitting, I agree :-)
> In an old generation kernel this might be optionally enabled in the .config
> file, as NAPI is in the 2.6.35 FEC drivers I'm stuck with using at the
> moment on the i.MX53. In the current kernel, could this mode of operation
> (and/or hardware FIFO using NAPI) be made configurable in the Device Tree
> instead?
Why would you want to do that? It should be known to either work or not for
specific hardware (-version), so the decision can be hard-coded in the driver.
In other words: if RX-FIFO works fine for your chip, why would you ever want
to disable it in the DT?
Best regards,
--
David Jander
Protonic Holland.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 8:17 ` Tom Evans
2015-09-03 8:38 ` David Jander
@ 2015-09-03 8:45 ` Marc Kleine-Budde
1 sibling, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-03 8:45 UTC (permalink / raw)
To: tom_usenet, David Jander; +Cc: kernel, linux-can
[-- Attachment #1: Type: text/plain, Size: 3069 bytes --]
On 09/03/2015 10:17 AM, Tom Evans wrote:
> On 03/09/15 16:58, Marc Kleine-Budde wrote:
>> On 09/03/2015 08:32 AM, David Jander wrote:
>>>>> this series adds a software FIFO implementation and switches
>
> Thank you both for explaining that.
>
> It seems fairly bulletproof as long as it doesn't overflow. There are 64
> buffers, so 32 in the first half, so that handles a 1.5ms interrupt latency.
>
> A shame Freescale didn't think of that method instead of requiring the driver
> run quicksort somewhere.
>
> > In an atomic operation, the MB's that have been served are
> > now disabled.
>
> That's the sort of tricky operation that exposes nasty silicon bugs. I'd
> suggest that this mode be made easy to turn off in case some chip variant has
> a problem like htis.
This mode is only enabled on imx6, vybid and newer, as all the other
cores cannot receive RTR frames in the non FIFO mode.
> This feature looks to be enabled as a "QUIRK" of the CPU.
The quirk to enable the non FIFO mode, a.k.a. SW_FIFO is called
FLEXCAN_QUIRK_USE_SW_FIFO. See patch 7/8 where it is enabled on imx6 and
vybrid.
> In an old generation kernel this might be optionally enabled in the .config
> file, as NAPI is in the 2.6.35 FEC drivers I'm stuck with using at the moment
> on the i.MX53. In the current kernel, could this mode of operation (and/or
> hardware FIFO using NAPI) be made configurable in the Device Tree instead?
Since 4.0 or something you really want to use NAPI, otherwise the order
of the packages is not guaranteed by the networking stack. So in both
case we use NAPI, but read the CAN frames in the hard IRQ context.
Either with the traditional FIFO (on that powerpc, imx25, imx35, imx53
and imx28) or the non-FIFO mode (imx6, vybrid).
With the current implementation, when enabling FLEXCAN_QUIRK_USE_SW_FIFO
on mx28, the controller doesn't receive RTR and extended CAN frames. RTR
is a known issue for the older cores, whie extended frames is probably a
configuration issue.
Given that the extended frame issue is fixed, you might want to
sacrifice RTR reception (because you don't need it) for bigger buffers
you can either patch the driver (adding the FLEXCAN_QUIRK_USE_SW_FIFO),
add a device tree option (convince the reviewers that this not a
confiuration option but a hardware description) or make it a new
CAN_CTRLMODE, so that it can be configured from the userspace.
According to the documentation both the normal FIFO and the mailboxes
can be used for RX at the same time, we can try to setup filters, so
that the FIFO is used for RTR messages only, while the normal mailboxes
are used for the non RTR messages. In order to merge these two together
we probably need to evaluate the timestamps.
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] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 8:38 ` David Jander
@ 2015-09-03 8:47 ` Marc Kleine-Budde
2015-09-04 3:19 ` Tom Evans
1 sibling, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2015-09-03 8:47 UTC (permalink / raw)
To: David Jander, Tom Evans; +Cc: linux-can, kernel
[-- Attachment #1: Type: text/plain, Size: 533 bytes --]
On 09/03/2015 10:38 AM, David Jander wrote:
> The fact that these "FEATURE" bits where all renamed to be "QUIRK"s is 75%
> better than before, but in this case (the other 25%) the name "FEATURE" would
> be more fitting, I agree :-)
lol :)
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] 17+ messages in thread
* Re: [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading
2015-09-03 8:38 ` David Jander
2015-09-03 8:47 ` Marc Kleine-Budde
@ 2015-09-04 3:19 ` Tom Evans
1 sibling, 0 replies; 17+ messages in thread
From: Tom Evans @ 2015-09-04 3:19 UTC (permalink / raw)
To: David Jander; +Cc: Marc Kleine-Budde, linux-can, kernel
On 03/09/15 18:38, David Jander wrote:
> On Thu, 3 Sep 2015 18:17:53 +1000
> Tom Evans <tom_usenet@optusnet.com.au> wrote:
>
>> On 03/09/15 16:58, Marc Kleine-Budde wrote:
>>> On 09/03/2015 08:32 AM, David Jander wrote:
>>>>>> this series adds a software FIFO implementation and switches
>>
>> Thank you both for explaining that.
And the further explanations and background in the followup email.
Could some of this be added to a documentation file somewhere, or added as a
paragraph above the QUIRKS table? The existing code definitions and commments
may be sufficient for people who have been fighting these chips for years, but
not for someone relatively new to these chips.
>> In an old generation kernel this might be optionally enabled
>
> Why would you want to do that?
For when a new driver is released, and doesn't work for some users.
> It should be known to either work or not for specific hardware (-version),
It should, but sometimes something goes wrong and someone may need to easily
back out of a new feature to be able to use a new kernel version.
Tom
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-09-04 3:19 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-01 10:31 [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 1/8] can: flexcan: add missing register definitions Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 2/8] can: flexcan: activate individual RX masking and initialize reg_rximr Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 3/8] can: flexcan: add quirk FLEXCAN_QUIRK_ENABLE_EACEN_RRS Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 4/8] can: flexcan: reg_imask2_default Marc Kleine-Budde
2015-09-01 10:31 ` [PATCH 5/8] can: rx-fifo: introduce software rx-fifo implementation Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 6/8] can: flexcan: add support for rx-fifo based software FIFO implementation Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 7/8] can: flexcan: switch imx6 and vf610 to software based fifo Marc Kleine-Budde
2015-09-01 10:32 ` [PATCH 8/8] can: at91_can: switch to rx-fifo implementation Marc Kleine-Budde
2015-09-02 23:58 ` [PATCH 0/8] RFC: more flexcan cleanups and SW FIFO IRQ offloading Tom Evans
2015-09-03 6:32 ` David Jander
2015-09-03 6:58 ` Marc Kleine-Budde
2015-09-03 8:17 ` Tom Evans
2015-09-03 8:38 ` David Jander
2015-09-03 8:47 ` Marc Kleine-Budde
2015-09-04 3:19 ` Tom Evans
2015-09-03 8:45 ` Marc Kleine-Budde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).