diff options
author | Brian Swetland <swetland@google.com> | 2009-10-30 19:22:05 -0400 |
---|---|---|
committer | Daniel Walker <dwalker@codeaurora.org> | 2010-05-12 12:15:21 -0400 |
commit | 34f719b0c25cca6e11164f926fc798c25499aa96 (patch) | |
tree | be4b551d1d7d492a924240858ad822fbc760fbcc /arch/arm | |
parent | 7632fba05197999fb0d24776b567682ebd62f62a (diff) |
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')
-rw-r--r-- | arch/arm/mach-msm/smd.c | 13 |
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); | |||
153 | static unsigned char smd_ch_allocated[64]; | 153 | static unsigned char smd_ch_allocated[64]; |
154 | static struct work_struct probe_work; | 154 | static struct work_struct probe_work; |
155 | 155 | ||
156 | static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type); | 156 | static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type); |
157 | 157 | ||
158 | static void smd_channel_probe_worker(struct work_struct *work) | 158 | static void smd_channel_probe_worker(struct work_struct *work) |
159 | { | 159 | { |
@@ -186,8 +186,8 @@ static void smd_channel_probe_worker(struct work_struct *work) | |||
186 | type = shared[n].ctype & SMD_TYPE_MASK; | 186 | type = shared[n].ctype & SMD_TYPE_MASK; |
187 | if ((type == SMD_TYPE_APPS_MODEM) || | 187 | if ((type == SMD_TYPE_APPS_MODEM) || |
188 | (type == SMD_TYPE_APPS_DSP)) | 188 | (type == SMD_TYPE_APPS_DSP)) |
189 | smd_alloc_channel(shared[n].name, shared[n].cid, ctype); | 189 | if (!smd_alloc_channel(shared[n].name, shared[n].cid, ctype)) |
190 | smd_ch_allocated[n] = 1; | 190 | smd_ch_allocated[n] = 1; |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
@@ -641,20 +641,20 @@ static int smd_alloc_v1(struct smd_channel *ch) | |||
641 | } | 641 | } |
642 | 642 | ||
643 | 643 | ||
644 | static void smd_alloc_channel(const char *name, uint32_t cid, uint32_t type) | 644 | static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type) |
645 | { | 645 | { |
646 | struct smd_channel *ch; | 646 | struct smd_channel *ch; |
647 | 647 | ||
648 | ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL); | 648 | ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL); |
649 | if (ch == 0) { | 649 | if (ch == 0) { |
650 | pr_err("smd_alloc_channel() out of memory\n"); | 650 | pr_err("smd_alloc_channel() out of memory\n"); |
651 | return; | 651 | return -1; |
652 | } | 652 | } |
653 | ch->n = cid; | 653 | ch->n = cid; |
654 | 654 | ||
655 | if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) { | 655 | if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) { |
656 | kfree(ch); | 656 | kfree(ch); |
657 | return; | 657 | return -1; |
658 | } | 658 | } |
659 | 659 | ||
660 | ch->fifo_mask = ch->fifo_size - 1; | 660 | 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) | |||
696 | mutex_unlock(&smd_creation_mutex); | 696 | mutex_unlock(&smd_creation_mutex); |
697 | 697 | ||
698 | platform_device_register(&ch->pdev); | 698 | platform_device_register(&ch->pdev); |
699 | return 0; | ||
699 | } | 700 | } |
700 | 701 | ||
701 | static void do_nothing_notify(void *priv, unsigned flags) | 702 | static void do_nothing_notify(void *priv, unsigned flags) |