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>
This commit is contained in:
Jeff Hugo
2011-11-15 16:39:20 -07:00
parent 9a2fab5067
commit 347fbbb117

View File

@@ -308,6 +308,7 @@ static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
}
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 @@ static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
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 @@ xmit_out:
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);
}