With this patch the driver is able to sustain a transmit data stream
without gaps between messages.

Signed-off-by: David Jander <[email protected]>
---
 drivers/net/can/mcp251x.c |   37 ++++++++++++++++++++++++++++++-------
 1 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 32037d8..ce5e2f1 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -202,7 +202,7 @@
 #define SPI_TRANSFER_BUF_LEN   (6 + CAN_FRAME_MAX_DATA_LEN)
 #define CAN_FRAME_MAX_BITS     128
 
-#define TX_ECHO_SKB_MAX        1
+#define TX_ECHO_SKB_MAX        2
 
 #define DEVICE_NAME "mcp251x"
 
@@ -248,18 +248,22 @@ struct mcp251x_priv {
 #define AFTER_SUSPEND_POWER 4
 #define AFTER_SUSPEND_RESTART 8
        int restart_tx;
+       int tx_buf_busy_mask;
 };
 
 static void mcp251x_clean(struct net_device *net)
 {
        struct mcp251x_priv *priv = netdev_priv(net);
 
-       if (priv->tx_skb || priv->tx_len)
+       if (priv->tx_skb || priv->tx_buf_busy_mask)
                net->stats.tx_errors++;
        if (priv->tx_skb)
                dev_kfree_skb(priv->tx_skb);
-       if (priv->tx_len)
+       if (priv->tx_buf_busy_mask & 1)
                can_free_echo_skb(priv->net, 0);
+       if (priv->tx_buf_busy_mask & 2)
+               can_free_echo_skb(priv->net, 1);
+
        priv->tx_skb = NULL;
        priv->tx_len = 0;
 }
@@ -491,7 +495,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff 
*skb,
        struct mcp251x_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
 
-       if (priv->tx_skb || priv->tx_len) {
+       if (priv->tx_skb || ((priv->tx_buf_busy_mask & 3) == 3)) {
                dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
                return NETDEV_TX_BUSY;
        }
@@ -726,10 +730,20 @@ static void mcp251x_tx_work_handler(struct work_struct 
*ws)
 
                        if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
                                frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
-                       mcp251x_hw_tx(spi, frame, 0);
+                       if ((priv->tx_buf_busy_mask & 1) == 0) {
+                               mcp251x_hw_tx(spi, frame, 0);
+                               priv->tx_buf_busy_mask |= 1;
+                               can_put_echo_skb(priv->tx_skb, net, 0);
+                       } else if ((priv->tx_buf_busy_mask & 2) == 0) {
+                               mcp251x_hw_tx(spi, frame, 1);
+                               priv->tx_buf_busy_mask |= 2;
+                               can_put_echo_skb(priv->tx_skb, net, 1);
+                       }
                        priv->tx_len = 1 + frame->can_dlc;
-                       can_put_echo_skb(priv->tx_skb, net, 0);
+
                        priv->tx_skb = NULL;
+                       if (priv->tx_buf_busy_mask < 3)
+                               netif_wake_queue(net);
                }
        }
        mutex_unlock(&priv->mcp_lock);
@@ -868,9 +882,17 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                        net->stats.tx_packets++;
                        net->stats.tx_bytes += priv->tx_len - 1;
                        if (priv->tx_len) {
-                               can_get_echo_skb(net, 0);
                                priv->tx_len = 0;
                        }
+                       if (intf & CANINTF_TX0IF) {
+                               can_get_echo_skb(net, 0);
+                               priv->tx_buf_busy_mask &= ~1;
+                       }
+                       if (intf & CANINTF_TX1IF) {
+                               can_get_echo_skb(net, 1);
+                               priv->tx_buf_busy_mask &= ~2;
+                       }
+
                        netif_wake_queue(net);
                }
 
@@ -977,6 +999,7 @@ static int __devinit mcp251x_can_probe(struct spi_device 
*spi)
        dev_set_drvdata(&spi->dev, priv);
 
        priv->spi = spi;
+       priv->tx_buf_busy_mask = 0;
        mutex_init(&priv->mcp_lock);
 
        /* If requested, allocate DMA buffers */
-- 
1.6.3.3

_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to