Merge "msm: sps: Fix BAM ISR race with pipe disconnect"
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 7716ccb..5ad281d 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -165,7 +165,8 @@
list_for_each_entry(pipe, &dev->pipes_q, list) {
/* Check this pipe's bit in the source mask */
- if ((source & pipe->pipe_index_mask)) {
+ if (BAM_PIPE_IS_ASSIGNED(pipe)
+ && (source & pipe->pipe_index_mask)) {
/* This pipe has an interrupt pending */
pipe_handler(dev, pipe);
source &= ~pipe->pipe_index_mask;
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index ccdeaf7..2b46203 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include <linux/list.h> /* list_head */
#include <linux/slab.h> /* kzalloc() */
#include <linux/memory.h> /* memset */
+#include <linux/interrupt.h>
#include "spsi.h"
#include "sps_core.h"
@@ -555,8 +556,11 @@
{
struct sps_connection *map = (void *)pipe->map;
struct sps_connect *cfg = &pipe->connect;
+ struct sps_bam *bam = pipe->bam;
+ unsigned long flags;
mutex_lock(&sps_rm->lock);
+ spin_lock_irqsave(&bam->isr_lock, flags);
/* Free this connection */
if (cfg->mode == SPS_MODE_SRC)
@@ -570,6 +574,7 @@
sps_rm_remove_ref(map);
+ spin_unlock_irqrestore(&bam->isr_lock, flags);
mutex_unlock(&sps_rm->lock);
return 0;
@@ -782,6 +787,8 @@
if (pipe->client_state == SPS_STATE_CONNECT &&
state == SPS_STATE_DISCONNECT) {
struct sps_connection *map;
+ struct sps_bam *bam = pipe->bam;
+ unsigned long flags;
u32 pipe_index;
if (pipe->connect.mode == SPS_MODE_SRC)
@@ -789,8 +796,12 @@
else
pipe_index = pipe->map->dest.pipe_index;
+ if (bam->props.irq > 0)
+ synchronize_irq(bam->props.irq);
+ spin_lock_irqsave(&bam->isr_lock, flags);
result = sps_bam_pipe_disconnect(pipe->bam, pipe_index);
+ spin_unlock_irqrestore(&bam->isr_lock, flags);
if (result) {
SPS_ERR("sps:Failed to disconnect BAM 0x%x pipe %d",
pipe->bam->props.phys_addr,