summaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2009-10-31 02:22:05 +0300
committerDaniel Walker <dwalker@codeaurora.org>2010-05-12 20:15:21 +0400
commit34f719b0c25cca6e11164f926fc798c25499aa96 (patch)
treebe4b551d1d7d492a924240858ad822fbc760fbcc /arch/arm/mach-msm
parent7632fba05197999fb0d24776b567682ebd62f62a (diff)
downloadlinux-34f719b0c25cca6e11164f926fc798c25499aa96.tar.xz
msm/qsd: smd: avoid race condition in smd channel allocation
Don't mark a channel as allocated if we failed to allocate it (perhaps the modem updated one table but not the other, etc) Signed-off-by: Brian Swetland <swetland@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/smd.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 3fbba444e99c..34bcc327aa88 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -153,7 +153,7 @@ LIST_HEAD(smd_ch_list_dsp);
static unsigned char smd_ch_allocated[64];
static struct work_struct probe_work;
-static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
+static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type);
static void smd_channel_probe_worker(struct work_struct *work)
{
@@ -186,8 +186,8 @@ static void smd_channel_probe_worker(struct work_struct *work)
type = shared[n].ctype & SMD_TYPE_MASK;
if ((type == SMD_TYPE_APPS_MODEM) ||
(type == SMD_TYPE_APPS_DSP))
- smd_alloc_channel(shared[n].name, shared[n].cid, ctype);
- smd_ch_allocated[n] = 1;
+ if (!smd_alloc_channel(shared[n].name, shared[n].cid, ctype))
+ smd_ch_allocated[n] = 1;
}
}
@@ -641,20 +641,20 @@ static int smd_alloc_v1(struct smd_channel *ch)
}
-static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
+static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
{
struct smd_channel *ch;
ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL);
if (ch == 0) {
pr_err("smd_alloc_channel() out of memory\n");
- return;
+ return -1;
}
ch->n = cid;
if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) {
kfree(ch);
- return;
+ return -1;
}
ch->fifo_mask = ch->fifo_size - 1;
@@ -696,6 +696,7 @@ static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
mutex_unlock(&smd_creation_mutex);
platform_device_register(&ch->pdev);
+ return 0;
}
static void do_nothing_notify(void *priv, unsigned flags)