msm: rmnet_bam: fix xmit statistics

The skb being transmitted can be freed at any point after handing it
off to the transport.  Thus the statistics must be determined in the
callback to prevent accessing data that is already freed.  Also,
statistics should always be calculated when in IP mode.

CRs-Fixed: 318747
Change-Id: I3a2a081291fc657ca64aff47a3370017c5b6f7ca
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 3b3758e..bb20a3f 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -308,6 +308,7 @@
 	}
 
 	dev->trans_start = jiffies;
+	/* if write() succeeds, skb access is unsafe in this process */
 	bam_ret = msm_bam_dmux_write(p->ch_id, skb);
 
 	if (bam_ret != 0) {
@@ -316,16 +317,6 @@
 		goto xmit_out;
 	}
 
-	if (count_this_packet(skb->data, skb->len)) {
-		p->stats.tx_packets++;
-		p->stats.tx_bytes += skb->len;
-#ifdef CONFIG_MSM_RMNET_DEBUG
-		p->wakeups_xmit += rmnet_cause_wakeup(p);
-#endif
-	}
-	DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
-	    dev->name, p->stats.tx_packets, skb->len, skb->mark);
-
 	return 0;
 xmit_out:
 	/* data xmited, safe to release skb */
@@ -335,7 +326,21 @@
 
 static void bam_write_done(void *dev, struct sk_buff *skb)
 {
+	struct rmnet_private *p = netdev_priv(dev);
+	u32 opmode = p->operation_mode;
+
 	DBG1("%s: write complete\n", __func__);
+	if (RMNET_IS_MODE_IP(opmode) ||
+				count_this_packet(skb->data, skb->len)) {
+		p->stats.tx_packets++;
+		p->stats.tx_bytes += skb->len;
+#ifdef CONFIG_MSM_RMNET_DEBUG
+		p->wakeups_xmit += rmnet_cause_wakeup(p);
+#endif
+	}
+	DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
+	    ((struct net_device *)(dev))->name, p->stats.tx_packets,
+	    skb->len, skb->mark);
 	dev_kfree_skb_any(skb);
 	netif_wake_queue(dev);
 }