From: David Jander <[email protected]> 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
