Commit 71001a9c authored by Hiroshi DOYU's avatar Hiroshi DOYU Committed by Juha Yrjola

ARM: OMAP: DSPGW: Fix deadlock

Signed-off-by: default avatarHiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: default avatarJuha Yrjola <juha.yrjola@solidboot.com>
parent 48fb11a2
......@@ -155,13 +155,38 @@ int sync_with_dsp(u16 *adr, u16 val, int try_cnt)
return -1;
}
static int mbcmd_sender_prepare(void *data)
{
struct mb_exarg *arg = data;
int i, ret = 0;
/*
* even if ipbuf_sys_ad is in DSP internal memory,
* dsp_mem_enable() never cause to call PM mailbox command
* because in that case DSP memory should be always enabled.
* (see ipbuf_sys_hold_mem_active in ipbuf.c)
*
* Therefore, we can call this function here safely.
*/
if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) {
printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
ret = -EBUSY;
goto out;
}
for (i = 0; i < arg->argc; i++) {
ipbuf_sys_ad->d[i] = arg->argv[i];
}
ipbuf_sys_ad->s = arg->tid;
out:
return ret;
}
/*
* __dsp_mbcmd_send_exarg(): mailbox dispatcher
*/
int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
int recovery_flag)
{
static DEFINE_MUTEX(mbsend_lock);
int ret = 0;
/*
......@@ -172,46 +197,24 @@ int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg,
printk(KERN_ERR
"mbox: mmu interrupt is set. %s is aborting.\n",
cmd_name(*mb));
return -1;
goto out;
}
if (mutex_lock_interruptible(&mbsend_lock) < 0)
return -1;
if (arg) { /* we have extra argument */
int i;
/*
* even if ipbuf_sys_ad is in DSP internal memory,
* dsp_mem_enable() never cause to call PM mailbox command
* because in that case DSP memory should be always enabled.
* (see ipbuf_sys_hold_mem_active in ipbuf.c)
*
* Therefore, we can call this function here safely.
*/
if (arg)
dsp_mem_enable(ipbuf_sys_ad);
if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) {
printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n");
dsp_mem_disable(ipbuf_sys_ad);
ret = -EBUSY;
ret = omap_mbox_msg_send(mbox_dsp, *(mbox_msg_t *)mb, (void*)arg);
if (ret)
goto out;
}
for (i = 0; i < arg->argc; i++) {
ipbuf_sys_ad->d[i] = arg->argv[i];
}
ipbuf_sys_ad->s = arg->tid;
dsp_mem_disable(ipbuf_sys_ad);
}
if (mbseq)
mbseq->ad_arm++;
mblog_add(mb, DIR_A2D);
out:
if (arg)
dsp_mem_disable(ipbuf_sys_ad);
ret = omap_mbox_msg_send(mbox_dsp, *(mbox_msg_t *)mb);
out:
mutex_unlock(&mbsend_lock);
return ret;
}
......@@ -311,14 +314,16 @@ static int __init dsp_mbox_init(void)
return -ENODEV;
}
mbox_dsp->mbox->msg_receive_cb = mbcmd_receiver;
mbox_dsp->msg_receive_cb = mbcmd_receiver;
mbox_dsp->msg_sender_cb = mbcmd_sender_prepare;
return 0;
}
static void dsp_mbox_exit(void)
{
mbox_dsp->mbox->msg_receive_cb = NULL;
mbox_dsp->msg_sender_cb = NULL;
mbox_dsp->msg_receive_cb = NULL;
if (mbsync_hold_mem_active) {
dsp_mem_disable((void *)daram_base);
......
......@@ -3,52 +3,66 @@
#ifndef MAILBOX_H
#define MAILBOX_H
#include <linux/wait.h>
#include <linux/workqueue.h>
typedef u32 mbox_msg_t;
typedef void (mbox_receiver_t)(mbox_msg_t msg);
struct omap_mbox;
struct omap_mbq;
typedef int __bitwise omap_mbox_irq_t;
#define IRQ_TX ((__force omap_mbox_irq_t) 1)
#define IRQ_RX ((__force omap_mbox_irq_t) 2)
typedef int __bitwise omap_mbox_type_t;
#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
struct omap_mbox_ops {
omap_mbox_type_t type;
int (*startup)(struct omap_mbox *mbox);
void (*shutdown)(struct omap_mbox *mbox);
/* fifo */
mbox_msg_t (*fifo_read)(struct omap_mbox *mbox);
void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
int (*fifo_empty)(struct omap_mbox *mbox);
int (*fifo_full)(struct omap_mbox *mbox);
/* irq */
void (*enable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
};
struct omap_mbox {
char *name;
spinlock_t lock;
unsigned int irq;
struct omap_mbox_ops *ops;
wait_queue_head_t tx_waitq;
struct work_struct msg_receive;
void (*msg_receive_cb)(mbox_msg_t);
struct omap_mbq *mbq;
int (*msg_sender_cb)(void*);
mbox_msg_t seq_snd, seq_rcv;
struct class_device class_dev;
void *priv;
struct omap_mbox *next;
};
int omap_mbox_msg_send(struct omap_mbox *mbox_h, mbox_msg_t msg, void* arg);
void omap_mbox_init_seq(struct omap_mbox *mbox);
struct mbox; /* contents are private */
struct mbox *mbox_get(const char *id);
extern int mbox_send(struct mbox *mbox_h, mbox_msg_t msg);
extern int register_mbox_receiver(struct mbox *mbox, unsigned char cmd,
mbox_receiver_t *rcv);
extern int unregister_mbox_receiver(struct mbox *mbox, unsigned char cmd,
mbox_receiver_t *rcv);
extern void enable_mbox_irq(struct mbox *mbox);
extern void disable_mbox_irq(struct mbox *mbox);
extern void mbox_init_seq(struct mbox *mbox);
/*
* mailbox command: 0x00 - 0x7f
* when a driver wants to use mailbox, it must reserve mailbox commands here.
*/
#define MBOX_CMD_MAX 0x80
/* DSP Gateway */
#define MBOX_CMD_DSP_WDSND 0x10
#define MBOX_CMD_DSP_WDREQ 0x11
#define MBOX_CMD_DSP_BKSND 0x20
#define MBOX_CMD_DSP_BKREQ 0x21
#define MBOX_CMD_DSP_BKYLD 0x23
#define MBOX_CMD_DSP_BKSNDP 0x24
#define MBOX_CMD_DSP_BKREQP 0x25
#define MBOX_CMD_DSP_TCTL 0x30
#define MBOX_CMD_DSP_TCTLDATA 0x31
#define MBOX_CMD_DSP_POLL 0x32
#define MBOX_CMD_DSP_WDT 0x50
#define MBOX_CMD_DSP_RUNLEVEL 0x51
#define MBOX_CMD_DSP_PM 0x52
#define MBOX_CMD_DSP_SUSPEND 0x53
#define MBOX_CMD_DSP_KFUNC 0x54
#define MBOX_CMD_DSP_TCFG 0x60
#define MBOX_CMD_DSP_TADD 0x62
#define MBOX_CMD_DSP_TDEL 0x63
#define MBOX_CMD_DSP_TSTOP 0x65
#define MBOX_CMD_DSP_DSPCFG 0x70
#define MBOX_CMD_DSP_REGRW 0x72
#define MBOX_CMD_DSP_GETVAR 0x74
#define MBOX_CMD_DSP_SETVAR 0x75
#define MBOX_CMD_DSP_ERR 0x78
#define MBOX_CMD_DSP_DBG 0x79
struct omap_mbox *omap_mbox_get(const char *name);
int omap_mbox_register(struct omap_mbox *mbox);
int omap_mbox_unregister(struct omap_mbox *mbox);
#endif /* MAILBOX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment