[PATCH] can: m_can: Fix tx bytes counting if local loop-back is disabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In case can frames are sent with local loop-back disabled, for instance
doing a "cangen -x", tx_bytes stats are not updated properly in
m_can_echo_tx_event().

More in details, if local loop-back is off, then echo skb is not set
by can_put_echo_skb() at the time m_can_start_xmit() calls it.
So later when tx event interrupt is raised and m_can_echo_tx_event() is
called, can_get_echo_skb() returns 0 and stats->tx_bytes is not
incremented.

In m_can_echo_tx_event(), this patch checks whether message marker
matches a valid skb and if not, data len is retrieved reading tx event
fifo instead of relying on can_get_echo_skb().

This patch has been tested with the ST Accordo5 machine, not yet supported
upstream but which relies on the m_can driver.

Signed-off-by: Jean-Nicolas Graux <jean-nicolas.graux@xxxxxx>
---
 drivers/net/can/m_can/m_can.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 9b44940..791a5c6 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -346,6 +346,8 @@ enum m_can_mram_cfg {
 /* E1 */
 #define TX_EVENT_MM_SHIFT	TX_BUF_MM_SHIFT
 #define TX_EVENT_MM_MASK	(0xff << TX_EVENT_MM_SHIFT)
+#define TX_EVENT_DLC_SHIFT	16
+#define TX_EVENT_DLC_MASK	(0xF << TX_EVENT_DLC_SHIFT)
 
 /* address offset and element number for each FIFO/Buffer in the Message RAM */
 struct mram_cfg {
@@ -847,7 +849,7 @@ static void m_can_echo_tx_event(struct net_device *dev)
 	u32 m_can_txefs;
 	u32 fgi = 0;
 	int i = 0;
-	unsigned int msg_mark;
+	unsigned int msg_mark, txe;
 
 	struct m_can_priv *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &dev->stats;
@@ -866,15 +868,21 @@ static void m_can_echo_tx_event(struct net_device *dev)
 			>> TXEFS_EFGI_SHIFT;
 
 		/* get message marker */
-		msg_mark = (m_can_txe_fifo_read(priv, fgi, 4) &
-			    TX_EVENT_MM_MASK) >> TX_EVENT_MM_SHIFT;
+		txe = m_can_txe_fifo_read(priv, fgi, 4);
+		msg_mark = (txe & TX_EVENT_MM_MASK) >> TX_EVENT_MM_SHIFT;
 
 		/* ack txe element */
 		m_can_write(priv, M_CAN_TXEFA, (TXEFA_EFAI_MASK &
 						(fgi << TXEFA_EFAI_SHIFT)));
 
 		/* update stats */
-		stats->tx_bytes += can_get_echo_skb(dev, msg_mark);
+		if (priv->can.echo_skb[msg_mark]) {
+			stats->tx_bytes += can_get_echo_skb(dev, msg_mark);
+		} else {
+			u32 dlc = (txe & TX_EVENT_DLC_MASK) >>
+				  TX_EVENT_DLC_SHIFT;
+			stats->tx_bytes += can_dlc2len(dlc);
+		}
 		stats->tx_packets++;
 	}
 }
-- 
2.7.4




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux