* [PATCH 1/2] can: c_can: support 64 message objects for D_CAN
[not found] <20190208131738.27668-1-andrejs.cainikovs@netmodule.com>
@ 2019-02-08 13:17 ` Andrejs Cainikovs
2019-07-24 9:48 ` Marc Kleine-Budde
2019-02-08 13:17 ` [PATCH 2/2] can: c_can: configurable amount of D_CAN RX objects Andrejs Cainikovs
1 sibling, 1 reply; 6+ messages in thread
From: Andrejs Cainikovs @ 2019-02-08 13:17 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, David S. Miller,
linux-can, netdev, linux-kernel
Cc: Patrick Zysset
D_CAN supports up to 128 message objects, comparing to 32 on C_CAN.
However, some CPUs with D_CAN controller have their own limits:
TI AM335x Sitara CPU, for example, supports max of 64 message objects.
This patch extends max D_CAN message objects up to 64.
Signed-off-by: Andrejs Cainikovs <andrejs.cainikovs@netmodule.com>
---
drivers/net/can/c_can/Kconfig | 12 ++++++++++++
drivers/net/can/c_can/c_can.c | 42 ++++++++++++++++++++++--------------------
drivers/net/can/c_can/c_can.h | 20 ++++++++++++++++----
3 files changed, 50 insertions(+), 24 deletions(-)
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
index 61ffc12d8fd8..6c1ada7291df 100644
--- a/drivers/net/can/c_can/Kconfig
+++ b/drivers/net/can/c_can/Kconfig
@@ -20,4 +20,16 @@ config CAN_C_CAN_PCI
---help---
This driver adds support for the C_CAN/D_CAN chips connected
to the PCI bus.
+
+config CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ bool "Use 64 message objects for D_CAN"
+ default n
+ ---help---
+ D_CAN supports up to 128 message objects, comparing to 32 on
+ C_CAN. However, some CPUs with D_CAN controller have their
+ own limits: TI AM335x Sitara CPU, for example, supports max
+ of 64 message objects.
+ Enabling this option extends max D_CAN message objects up to
+ 64.
+
endif
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 606b7d8ffe13..5d695b89b459 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -352,15 +352,6 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
}
}
-static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
- int iface)
-{
- int i;
-
- for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++)
- c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);
-}
-
static int c_can_handle_lost_msg_obj(struct net_device *dev,
int iface, int objno, u32 ctrl)
{
@@ -706,7 +697,16 @@ static void c_can_do_tx(struct net_device *dev)
struct net_device_stats *stats = &dev->stats;
u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
- clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ if (priv->type == BOSCH_D_CAN) {
+ pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
+ } else {
+#endif
+ pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ }
+#endif
+ clr = pend;
while ((idx = ffs(pend))) {
idx--;
@@ -817,7 +817,17 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
static inline u32 c_can_get_pending(struct c_can_priv *priv)
{
- u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
+ u32 pend;
+
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ if (priv->type == BOSCH_D_CAN) {
+ pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
+ } else {
+#endif
+ pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ }
+#endif
return pend;
}
@@ -828,8 +838,7 @@ static inline u32 c_can_get_pending(struct c_can_priv *priv)
* c_can core saves a received CAN message into the first free message
* object it finds free (starting with the lowest). Bits NEWDAT and
* INTPND are set for this message object indicating that a new message
- * has arrived. To work-around this issue, we keep two groups of message
- * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
+ * has arrived.
*
* We clear the newdat bit right away.
*
@@ -840,13 +849,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
struct c_can_priv *priv = netdev_priv(dev);
u32 pkts = 0, pend = 0, toread, n;
- /*
- * It is faster to read only one 16bit register. This is only possible
- * for a maximum number of 16 objects.
- */
- BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16,
- "Implementation does not support more message objects than 16");
-
while (quota > 0) {
if (!pend) {
pend = c_can_get_pending(priv);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 8acdc7fa4792..e44b686a70a2 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -23,9 +23,15 @@
#define C_CAN_H
/* message object split */
+
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+#define C_CAN_NO_OF_OBJECTS 64
+#else
#define C_CAN_NO_OF_OBJECTS 32
-#define C_CAN_MSG_OBJ_RX_NUM 16
-#define C_CAN_MSG_OBJ_TX_NUM 16
+#endif
+
+#define C_CAN_MSG_OBJ_TX_NUM (C_CAN_NO_OF_OBJECTS >> 1)
+#define C_CAN_MSG_OBJ_RX_NUM (C_CAN_NO_OF_OBJECTS - C_CAN_MSG_OBJ_TX_NUM)
#define C_CAN_MSG_OBJ_RX_FIRST 1
#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
@@ -35,9 +41,11 @@
#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
C_CAN_MSG_OBJ_TX_NUM - 1)
-#define C_CAN_MSG_OBJ_RX_SPLIT 9
-#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
+#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+#define RECEIVE_OBJECT_BITS 0xffffffff
+#else
#define RECEIVE_OBJECT_BITS 0x0000ffff
+#endif
enum reg {
C_CAN_CTRL_REG = 0,
@@ -76,6 +84,8 @@ enum reg {
C_CAN_NEWDAT2_REG,
C_CAN_INTPND1_REG,
C_CAN_INTPND2_REG,
+ C_CAN_INTPND3_REG,
+ C_CAN_INTPND4_REG,
C_CAN_MSGVAL1_REG,
C_CAN_MSGVAL2_REG,
C_CAN_FUNCTION_REG,
@@ -137,6 +147,8 @@ static const u16 reg_map_d_can[] = {
[C_CAN_NEWDAT2_REG] = 0x9E,
[C_CAN_INTPND1_REG] = 0xB0,
[C_CAN_INTPND2_REG] = 0xB2,
+ [C_CAN_INTPND3_REG] = 0xB4,
+ [C_CAN_INTPND4_REG] = 0xB6,
[C_CAN_MSGVAL1_REG] = 0xC4,
[C_CAN_MSGVAL2_REG] = 0xC6,
[C_CAN_IF1_COMREQ_REG] = 0x100,
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] can: c_can: configurable amount of D_CAN RX objects
[not found] <20190208131738.27668-1-andrejs.cainikovs@netmodule.com>
2019-02-08 13:17 ` [PATCH 1/2] can: c_can: support 64 message objects for D_CAN Andrejs Cainikovs
@ 2019-02-08 13:17 ` Andrejs Cainikovs
1 sibling, 0 replies; 6+ messages in thread
From: Andrejs Cainikovs @ 2019-02-08 13:17 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, David S. Miller,
linux-can, netdev, linux-kernel
Cc: Patrick Zysset
Make number of D_CAN RX message objects configurable. This will allow
having bigger (or smaller) RX buffer instead of 50/50 split for RX/TX.
Signed-off-by: Andrejs Cainikovs <andrejs.cainikovs@netmodule.com>
---
drivers/net/can/c_can/Kconfig | 8 ++++++
drivers/net/can/c_can/c_can.c | 64 +++++++++++++++++++++++++++++--------------
drivers/net/can/c_can/c_can.h | 16 +++++------
3 files changed, 58 insertions(+), 30 deletions(-)
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
index 6c1ada7291df..949d2d12d71e 100644
--- a/drivers/net/can/c_can/Kconfig
+++ b/drivers/net/can/c_can/Kconfig
@@ -32,4 +32,12 @@ config CAN_C_CAN_DCAN_64_MSG_OBJECTS
Enabling this option extends max D_CAN message objects up to
64.
+config CAN_C_CAN_DCAN_RX_MSG_OBJECTS
+ int "Specify amount of D_CAN RX message objects"
+ depends on CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ default 32
+ ---help---
+ Use specific number of message objects for RX, instead of
+ 50/50 split between RX/TX.
+
endif
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 5d695b89b459..675bc223e222 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -208,6 +208,26 @@ static const struct can_bittiming_const c_can_bittiming_const = {
.brp_inc = 1,
};
+static inline u64 c_can_get_mask(int bits)
+{
+ return ((u64)1 << bits) - 1;
+}
+
+static inline int c_can_ffs64(u64 x)
+{
+ int b;
+
+ b = ffs(x);
+
+ if (!b) {
+ b = ffs(x >> 32);
+ if (b)
+ b += 32;
+ }
+
+ return b;
+}
+
static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
{
if (priv->device)
@@ -695,24 +715,23 @@ static void c_can_do_tx(struct net_device *dev)
{
struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
- u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
+ u32 idx, obj, pkts = 0, bytes = 0;
+ u64 pend, clr;
+ /* Mask interrupt pending bits */
+ pend = priv->read_reg32(priv, C_CAN_INTPND1_REG);
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
if (priv->type == BOSCH_D_CAN) {
- pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
- } else {
-#endif
- pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
-#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ pend |= (u64)priv->read_reg32(priv, C_CAN_INTPND3_REG) << 32;
}
#endif
- clr = pend;
+ pend &= ~c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM);
+ clr = pend >> C_CAN_MSG_OBJ_RX_NUM;
- while ((idx = ffs(pend))) {
- idx--;
- pend &= ~(1 << idx);
- obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+ while ((obj = c_can_ffs64(pend))) {
+ pend &= ~((u64)1 << (obj - 1));
c_can_inval_tx_object(dev, IF_RX, obj);
+ idx = obj - C_CAN_MSG_OBJ_TX_FIRST;
can_get_echo_skb(dev, idx);
bytes += priv->dlc[idx];
pkts++;
@@ -736,19 +755,19 @@ static void c_can_do_tx(struct net_device *dev)
* raced with the hardware or failed to readout all upper
* objects in the last run due to quota limit.
*/
-static u32 c_can_adjust_pending(u32 pend)
+static u64 c_can_adjust_pending(u64 pend)
{
- u32 weight, lasts;
+ u64 weight, lasts;
- if (pend == RECEIVE_OBJECT_BITS)
+ if (pend == c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM))
return pend;
/*
* If the last set bit is larger than the number of pending
* bits we have a gap.
*/
- weight = hweight32(pend);
- lasts = fls(pend);
+ weight = hweight64(pend);
+ lasts = fls64(pend);
/* If the bits are linear, nothing to do */
if (lasts == weight)
@@ -777,11 +796,11 @@ static inline void c_can_rx_finalize(struct net_device *dev,
}
static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
- u32 pend, int quota)
+ u64 pend, int quota)
{
u32 pkts = 0, ctrl, obj;
- while ((obj = ffs(pend)) && quota > 0) {
+ while ((obj = c_can_ffs64(pend)) && quota > 0) {
pend &= ~BIT(obj - 1);
c_can_rx_object_get(dev, priv, obj);
@@ -815,13 +834,15 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
return pkts;
}
-static inline u32 c_can_get_pending(struct c_can_priv *priv)
+static inline u64 c_can_get_pending(struct c_can_priv *priv)
{
- u32 pend;
+ u64 pend;
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
if (priv->type == BOSCH_D_CAN) {
pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
+ pend |= (u64)priv->read_reg32(priv, C_CAN_NEWDAT3_REG) << 32;
+ pend &= c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM);
} else {
#endif
pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
@@ -847,7 +868,8 @@ static inline u32 c_can_get_pending(struct c_can_priv *priv)
static int c_can_do_rx_poll(struct net_device *dev, int quota)
{
struct c_can_priv *priv = netdev_priv(dev);
- u32 pkts = 0, pend = 0, toread, n;
+ u32 pkts = 0, n;
+ u64 pend = 0, toread;
while (quota > 0) {
if (!pend) {
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e44b686a70a2..4a0759ee249d 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -26,12 +26,12 @@
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
#define C_CAN_NO_OF_OBJECTS 64
+#define C_CAN_MSG_OBJ_RX_NUM CONFIG_CAN_C_CAN_DCAN_RX_MSG_OBJECTS
#else
#define C_CAN_NO_OF_OBJECTS 32
+#define C_CAN_MSG_OBJ_RX_NUM 16
#endif
-
-#define C_CAN_MSG_OBJ_TX_NUM (C_CAN_NO_OF_OBJECTS >> 1)
-#define C_CAN_MSG_OBJ_RX_NUM (C_CAN_NO_OF_OBJECTS - C_CAN_MSG_OBJ_TX_NUM)
+#define C_CAN_MSG_OBJ_TX_NUM (C_CAN_NO_OF_OBJECTS - C_CAN_MSG_OBJ_RX_NUM)
#define C_CAN_MSG_OBJ_RX_FIRST 1
#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
@@ -41,12 +41,6 @@
#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
C_CAN_MSG_OBJ_TX_NUM - 1)
-#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
-#define RECEIVE_OBJECT_BITS 0xffffffff
-#else
-#define RECEIVE_OBJECT_BITS 0x0000ffff
-#endif
-
enum reg {
C_CAN_CTRL_REG = 0,
C_CAN_CTRL_EX_REG,
@@ -82,6 +76,8 @@ enum reg {
C_CAN_TXRQST2_REG,
C_CAN_NEWDAT1_REG,
C_CAN_NEWDAT2_REG,
+ C_CAN_NEWDAT3_REG,
+ C_CAN_NEWDAT4_REG,
C_CAN_INTPND1_REG,
C_CAN_INTPND2_REG,
C_CAN_INTPND3_REG,
@@ -145,6 +141,8 @@ static const u16 reg_map_d_can[] = {
[C_CAN_TXRQST2_REG] = 0x8A,
[C_CAN_NEWDAT1_REG] = 0x9C,
[C_CAN_NEWDAT2_REG] = 0x9E,
+ [C_CAN_NEWDAT3_REG] = 0xA0,
+ [C_CAN_NEWDAT4_REG] = 0xA2,
[C_CAN_INTPND1_REG] = 0xB0,
[C_CAN_INTPND2_REG] = 0xB2,
[C_CAN_INTPND3_REG] = 0xB4,
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] can: c_can: support 64 message objects for D_CAN
2019-02-08 13:17 ` [PATCH 1/2] can: c_can: support 64 message objects for D_CAN Andrejs Cainikovs
@ 2019-07-24 9:48 ` Marc Kleine-Budde
2021-01-13 18:49 ` Ezequiel Garcia
0 siblings, 1 reply; 6+ messages in thread
From: Marc Kleine-Budde @ 2019-07-24 9:48 UTC (permalink / raw)
To: Andrejs Cainikovs, Wolfgang Grandegger, linux-can, linux-kernel
Cc: Patrick Zysset
[-- Attachment #1.1: Type: text/plain, Size: 1331 bytes --]
On 2/8/19 2:17 PM, Andrejs Cainikovs wrote:
> D_CAN supports up to 128 message objects, comparing to 32 on C_CAN.
> However, some CPUs with D_CAN controller have their own limits:
> TI AM335x Sitara CPU, for example, supports max of 64 message objects.
>
> This patch extends max D_CAN message objects up to 64.
Please don't make this a kconfig option.
According to you description this is a HW feature, so please add the max
number of messe objects to "struct c_can_driver_data" and adjust the
drvdata accordingly.
> static const struct of_device_id c_can_of_table[] = {
> { .compatible = "bosch,c_can", .data = &c_can_drvdata },
> { .compatible = "bosch,d_can", .data = &d_can_drvdata },
> { .compatible = "ti,dra7-d_can", .data = &dra7_dcan_drvdata },
> { .compatible = "ti,am3352-d_can", .data = &am3352_dcan_drvdata },
> { .compatible = "ti,am4372-d_can", .data = &am3352_dcan_drvdata },
> { /* sentinel */ },
> };
You probably have to pass it via "struct c_can_priv" so that it's
available in the c_can.c
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: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] can: c_can: support 64 message objects for D_CAN
2019-07-24 9:48 ` Marc Kleine-Budde
@ 2021-01-13 18:49 ` Ezequiel Garcia
2021-01-13 19:37 ` Marc Kleine-Budde
0 siblings, 1 reply; 6+ messages in thread
From: Ezequiel Garcia @ 2021-01-13 18:49 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Andrejs Cainikovs, Wolfgang Grandegger, linux-can, linux-kernel,
Patrick Zysset, Federico Rossi (fede.a.rossi@gmail.com),
Maximiliano Sonnaillon
Hi Andrejs, Marc,
On Wed, 24 Jul 2019 at 06:48, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 2/8/19 2:17 PM, Andrejs Cainikovs wrote:
> > D_CAN supports up to 128 message objects, comparing to 32 on C_CAN.
> > However, some CPUs with D_CAN controller have their own limits:
> > TI AM335x Sitara CPU, for example, supports max of 64 message objects.
> >
> > This patch extends max D_CAN message objects up to 64.
>
> Please don't make this a kconfig option.
>
> According to you description this is a HW feature, so please add the max
> number of messe objects to "struct c_can_driver_data" and adjust the
> drvdata accordingly.
>
> > static const struct of_device_id c_can_of_table[] = {
> > { .compatible = "bosch,c_can", .data = &c_can_drvdata },
> > { .compatible = "bosch,d_can", .data = &d_can_drvdata },
> > { .compatible = "ti,dra7-d_can", .data = &dra7_dcan_drvdata },
> > { .compatible = "ti,am3352-d_can", .data = &am3352_dcan_drvdata },
> > { .compatible = "ti,am4372-d_can", .data = &am3352_dcan_drvdata },
> > { /* sentinel */ },
> > };
>
> You probably have to pass it via "struct c_can_priv" so that it's
> available in the c_can.c
>
I came here to make the same suggestion :-)
Andrejs, do you think you could respin this patch? Or perhaps I can find
some time to do that myself, if that's OK with you.
Thanks,
Ezequiel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] can: c_can: support 64 message objects for D_CAN
2021-01-13 18:49 ` Ezequiel Garcia
@ 2021-01-13 19:37 ` Marc Kleine-Budde
0 siblings, 0 replies; 6+ messages in thread
From: Marc Kleine-Budde @ 2021-01-13 19:37 UTC (permalink / raw)
To: Ezequiel Garcia
Cc: Andrejs Cainikovs, linux-can, linux-kernel, Patrick Zysset,
Federico Rossi (fede.a.rossi@gmail.com),
Maximiliano Sonnaillon
[-- Attachment #1.1: Type: text/plain, Size: 667 bytes --]
On 1/13/21 7:49 PM, Ezequiel Garcia wrote:
[...]
>> You probably have to pass it via "struct c_can_priv" so that it's
>> available in the c_can.c
>>
>
> I came here to make the same suggestion :-)
>
> Andrejs, do you think you could respin this patch? Or perhaps I can find
> some time to do that myself, if that's OK with you.
Take the patches as is and improve them.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung West/Dortmund | Phone: +49-231-2826-924 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] can: c_can: configurable amount of D_CAN RX objects
2019-02-08 13:31 [PATCH 0/2] D_CAN RX buffer size improvements Andrejs Cainikovs
@ 2019-02-08 13:31 ` Andrejs Cainikovs
0 siblings, 0 replies; 6+ messages in thread
From: Andrejs Cainikovs @ 2019-02-08 13:31 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, David S . Miller,
linux-can, netdev, linux-kernel
Cc: Patrick Zysset
Make number of D_CAN RX message objects configurable. This will allow
having bigger (or smaller) RX buffer instead of 50/50 split for RX/TX.
Signed-off-by: Andrejs Cainikovs <andrejs.cainikovs@netmodule.com>
---
drivers/net/can/c_can/Kconfig | 8 ++++++
drivers/net/can/c_can/c_can.c | 64 +++++++++++++++++++++++++++++--------------
drivers/net/can/c_can/c_can.h | 16 +++++------
3 files changed, 58 insertions(+), 30 deletions(-)
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
index 6c1ada7291df..949d2d12d71e 100644
--- a/drivers/net/can/c_can/Kconfig
+++ b/drivers/net/can/c_can/Kconfig
@@ -32,4 +32,12 @@ config CAN_C_CAN_DCAN_64_MSG_OBJECTS
Enabling this option extends max D_CAN message objects up to
64.
+config CAN_C_CAN_DCAN_RX_MSG_OBJECTS
+ int "Specify amount of D_CAN RX message objects"
+ depends on CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ default 32
+ ---help---
+ Use specific number of message objects for RX, instead of
+ 50/50 split between RX/TX.
+
endif
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 5d695b89b459..675bc223e222 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -208,6 +208,26 @@ static const struct can_bittiming_const c_can_bittiming_const = {
.brp_inc = 1,
};
+static inline u64 c_can_get_mask(int bits)
+{
+ return ((u64)1 << bits) - 1;
+}
+
+static inline int c_can_ffs64(u64 x)
+{
+ int b;
+
+ b = ffs(x);
+
+ if (!b) {
+ b = ffs(x >> 32);
+ if (b)
+ b += 32;
+ }
+
+ return b;
+}
+
static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
{
if (priv->device)
@@ -695,24 +715,23 @@ static void c_can_do_tx(struct net_device *dev)
{
struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
- u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
+ u32 idx, obj, pkts = 0, bytes = 0;
+ u64 pend, clr;
+ /* Mask interrupt pending bits */
+ pend = priv->read_reg32(priv, C_CAN_INTPND1_REG);
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
if (priv->type == BOSCH_D_CAN) {
- pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
- } else {
-#endif
- pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
-#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
+ pend |= (u64)priv->read_reg32(priv, C_CAN_INTPND3_REG) << 32;
}
#endif
- clr = pend;
+ pend &= ~c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM);
+ clr = pend >> C_CAN_MSG_OBJ_RX_NUM;
- while ((idx = ffs(pend))) {
- idx--;
- pend &= ~(1 << idx);
- obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+ while ((obj = c_can_ffs64(pend))) {
+ pend &= ~((u64)1 << (obj - 1));
c_can_inval_tx_object(dev, IF_RX, obj);
+ idx = obj - C_CAN_MSG_OBJ_TX_FIRST;
can_get_echo_skb(dev, idx);
bytes += priv->dlc[idx];
pkts++;
@@ -736,19 +755,19 @@ static void c_can_do_tx(struct net_device *dev)
* raced with the hardware or failed to readout all upper
* objects in the last run due to quota limit.
*/
-static u32 c_can_adjust_pending(u32 pend)
+static u64 c_can_adjust_pending(u64 pend)
{
- u32 weight, lasts;
+ u64 weight, lasts;
- if (pend == RECEIVE_OBJECT_BITS)
+ if (pend == c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM))
return pend;
/*
* If the last set bit is larger than the number of pending
* bits we have a gap.
*/
- weight = hweight32(pend);
- lasts = fls(pend);
+ weight = hweight64(pend);
+ lasts = fls64(pend);
/* If the bits are linear, nothing to do */
if (lasts == weight)
@@ -777,11 +796,11 @@ static inline void c_can_rx_finalize(struct net_device *dev,
}
static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
- u32 pend, int quota)
+ u64 pend, int quota)
{
u32 pkts = 0, ctrl, obj;
- while ((obj = ffs(pend)) && quota > 0) {
+ while ((obj = c_can_ffs64(pend)) && quota > 0) {
pend &= ~BIT(obj - 1);
c_can_rx_object_get(dev, priv, obj);
@@ -815,13 +834,15 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
return pkts;
}
-static inline u32 c_can_get_pending(struct c_can_priv *priv)
+static inline u64 c_can_get_pending(struct c_can_priv *priv)
{
- u32 pend;
+ u64 pend;
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
if (priv->type == BOSCH_D_CAN) {
pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
+ pend |= (u64)priv->read_reg32(priv, C_CAN_NEWDAT3_REG) << 32;
+ pend &= c_can_get_mask(C_CAN_MSG_OBJ_RX_NUM);
} else {
#endif
pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
@@ -847,7 +868,8 @@ static inline u32 c_can_get_pending(struct c_can_priv *priv)
static int c_can_do_rx_poll(struct net_device *dev, int quota)
{
struct c_can_priv *priv = netdev_priv(dev);
- u32 pkts = 0, pend = 0, toread, n;
+ u32 pkts = 0, n;
+ u64 pend = 0, toread;
while (quota > 0) {
if (!pend) {
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index e44b686a70a2..4a0759ee249d 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -26,12 +26,12 @@
#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
#define C_CAN_NO_OF_OBJECTS 64
+#define C_CAN_MSG_OBJ_RX_NUM CONFIG_CAN_C_CAN_DCAN_RX_MSG_OBJECTS
#else
#define C_CAN_NO_OF_OBJECTS 32
+#define C_CAN_MSG_OBJ_RX_NUM 16
#endif
-
-#define C_CAN_MSG_OBJ_TX_NUM (C_CAN_NO_OF_OBJECTS >> 1)
-#define C_CAN_MSG_OBJ_RX_NUM (C_CAN_NO_OF_OBJECTS - C_CAN_MSG_OBJ_TX_NUM)
+#define C_CAN_MSG_OBJ_TX_NUM (C_CAN_NO_OF_OBJECTS - C_CAN_MSG_OBJ_RX_NUM)
#define C_CAN_MSG_OBJ_RX_FIRST 1
#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
@@ -41,12 +41,6 @@
#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
C_CAN_MSG_OBJ_TX_NUM - 1)
-#ifdef CONFIG_CAN_C_CAN_DCAN_64_MSG_OBJECTS
-#define RECEIVE_OBJECT_BITS 0xffffffff
-#else
-#define RECEIVE_OBJECT_BITS 0x0000ffff
-#endif
-
enum reg {
C_CAN_CTRL_REG = 0,
C_CAN_CTRL_EX_REG,
@@ -82,6 +76,8 @@ enum reg {
C_CAN_TXRQST2_REG,
C_CAN_NEWDAT1_REG,
C_CAN_NEWDAT2_REG,
+ C_CAN_NEWDAT3_REG,
+ C_CAN_NEWDAT4_REG,
C_CAN_INTPND1_REG,
C_CAN_INTPND2_REG,
C_CAN_INTPND3_REG,
@@ -145,6 +141,8 @@ static const u16 reg_map_d_can[] = {
[C_CAN_TXRQST2_REG] = 0x8A,
[C_CAN_NEWDAT1_REG] = 0x9C,
[C_CAN_NEWDAT2_REG] = 0x9E,
+ [C_CAN_NEWDAT3_REG] = 0xA0,
+ [C_CAN_NEWDAT4_REG] = 0xA2,
[C_CAN_INTPND1_REG] = 0xB0,
[C_CAN_INTPND2_REG] = 0xB2,
[C_CAN_INTPND3_REG] = 0xB4,
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-01-13 19:39 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20190208131738.27668-1-andrejs.cainikovs@netmodule.com>
2019-02-08 13:17 ` [PATCH 1/2] can: c_can: support 64 message objects for D_CAN Andrejs Cainikovs
2019-07-24 9:48 ` Marc Kleine-Budde
2021-01-13 18:49 ` Ezequiel Garcia
2021-01-13 19:37 ` Marc Kleine-Budde
2019-02-08 13:17 ` [PATCH 2/2] can: c_can: configurable amount of D_CAN RX objects Andrejs Cainikovs
2019-02-08 13:31 [PATCH 0/2] D_CAN RX buffer size improvements Andrejs Cainikovs
2019-02-08 13:31 ` [PATCH 2/2] can: c_can: configurable amount of D_CAN RX objects Andrejs Cainikovs
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).