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);