msm: bam_dmux: Add TX pool mismatch detection

Change logic to remove list node of current work
item instead of the head of the list to provide
more robust handling of out-of-order packets.

Change-Id: I0225d3fe66db42551a85df7a9ec451b83f6b5599
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b865f24..afcb3bc 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -416,17 +416,31 @@
 	struct sk_buff *skb;
 	struct bam_mux_hdr *hdr;
 	struct tx_pkt_info *info;
+	struct tx_pkt_info *info_expected;
 	unsigned long event_data;
-	struct list_head *node;
 	unsigned long flags;
 
 	if (in_global_reset)
 		return;
-	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
-	node = bam_tx_pool.next;
-	list_del(node);
-	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+
 	info = container_of(work, struct tx_pkt_info, work);
+
+	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
+	info_expected = list_first_entry(&bam_tx_pool,
+			struct tx_pkt_info, list_node);
+	if (unlikely(info != info_expected)) {
+		struct list_head *node;
+
+		pr_err("%s: bam_tx_pool mismatch .next=%p, list_node=%p\n",
+				__func__, bam_tx_pool.next, &info->list_node);
+		list_for_each(node, &bam_tx_pool)
+			pr_err("%s: node=%p\n", __func__, node);
+		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+		BUG();
+	}
+	list_del(&info->list_node);
+	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+
 	if (info->is_cmd) {
 		kfree(info->skb);
 		kfree(info);