C_CAN_MSG_OBJ_TX_FIRST;
 }
 
-static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv)
+static inline int get_tx_echo_msg_obj(int txecho)
 {
-       return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) +
-                       C_CAN_MSG_OBJ_TX_FIRST;
+       return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST;
 }
 
 static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index)
 }
 
 /*
- * theory of operation:
- *
  * priv->tx_echo holds the number of the oldest can_frame put for
  * transmission into the hardware, but not yet ACKed by the CAN tx
  * complete IRQ.
  */
 static void c_can_do_tx(struct net_device *dev)
 {
-       u32 val;
-       u32 msg_obj_no;
        struct c_can_priv *priv = netdev_priv(dev);
        struct net_device_stats *stats = &dev->stats;
+       u32 val, obj, pkts = 0, bytes = 0;
 
        spin_lock_bh(&priv->xmit_lock);
 
        for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
-               msg_obj_no = get_tx_echo_msg_obj(priv);
+               obj = get_tx_echo_msg_obj(priv->tx_echo);
                val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
-               if (!(val & (1 << (msg_obj_no - 1)))) {
-                       can_get_echo_skb(dev,
-                                       msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
-                       c_can_object_get(dev, IF_TX, msg_obj_no, IF_COMM_ALL);
-                       stats->tx_bytes += priv->read_reg(priv,
-                                       C_CAN_IFACE(MSGCTRL_REG, IF_TX))
-                                       & IF_MCONT_DLC_MASK;
-                       stats->tx_packets++;
-                       can_led_event(dev, CAN_LED_EVENT_TX);
-                       c_can_inval_msg_object(dev, IF_TX, msg_obj_no);
-               } else {
+
+               if (val & (1 << (obj - 1)))
                        break;
-               }
+
+               can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST);
+               bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST];
+               pkts++;
+               c_can_inval_msg_object(dev, IF_TX, obj);
        }
 
        /* restart queue if wrap-up or if queue stalled on last pkt */
                netif_wake_queue(dev);
 
        spin_unlock_bh(&priv->xmit_lock);
+
+       if (pkts) {
+               stats->tx_bytes += bytes;
+               stats->tx_packets += pkts;
+               can_led_event(dev, CAN_LED_EVENT_TX);
+       }
 }
 
 /*