soc: qcom: bam_dmux: Cache callback information

Callback notifications lock the channel status to prevent clients from
unregistering their callback function and other information while it is
in use during a notification.  However, in some scenarios, clients use
the notification context to call back into bam_dmux which can result in
lock recursion.

Avoid the issue by caching the callback information, and then unlocking
the channel state before invoking the client's callback.

CRs-Fixed: 690328
Change-Id: I764b1c21c2254c9c72ee329dc671f9a1afb648a2
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
This commit is contained in:
Jeff Hugo 2014-07-03 18:11:35 -06:00 committed by Arun Kumar Neelakantam
parent eddaea8d52
commit a38fd8aef3
1 changed files with 10 additions and 2 deletions

View File

@ -1615,14 +1615,22 @@ static void notify_all(int event, unsigned long data)
unsigned long flags;
struct list_head *temp;
struct outside_notify_func *func;
void (*notify)(void *, int, unsigned long);
void *priv;
BAM_DMUX_LOG("%s: event=%d, data=%lu\n", __func__, event, data);
for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
notify = NULL;
priv = NULL;
spin_lock_irqsave(&bam_ch[i].lock, flags);
if (bam_ch_is_open(i))
bam_ch[i].notify(bam_ch[i].priv, event, data);
if (bam_ch_is_open(i)) {
notify = bam_ch[i].notify;
priv = bam_ch[i].priv;
}
spin_unlock_irqrestore(&bam_ch[i].lock, flags);
if (notify)
notify(priv, event, data);
}
__list_for_each(temp, &bam_other_notify_funcs) {