From: Hiroshi DOYU Date: Thu, 21 Sep 2006 14:41:45 +0000 (+0300) Subject: ARM: OMAP: DSPGW: Fix deadlock X-Git-Tag: v2.6.18-omap1~45 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=71001a9ca099835fc8966d32a53548fe1a8acde0;p=linux-2.6-omap-h63xx.git ARM: OMAP: DSPGW: Fix deadlock Signed-off-by: Hiroshi DOYU Signed-off-by: Juha Yrjola --- diff --git a/arch/arm/plat-omap/dsp/dsp_core.c b/arch/arm/plat-omap/dsp/dsp_core.c index 76a9383a80d..09c0388bdce 100644 --- a/arch/arm/plat-omap/dsp/dsp_core.c +++ b/arch/arm/plat-omap/dsp/dsp_core.c @@ -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; - 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); - } + + ret = omap_mbox_msg_send(mbox_dsp, *(mbox_msg_t *)mb, (void*)arg); + if (ret) + goto out; 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); diff --git a/include/asm-arm/arch-omap/mailbox.h b/include/asm-arm/arch-omap/mailbox.h index e72be75c165..66669f07b95 100644 --- a/include/asm-arm/arch-omap/mailbox.h +++ b/include/asm-arm/arch-omap/mailbox.h @@ -3,52 +3,66 @@ #ifndef MAILBOX_H #define MAILBOX_H +#include +#include + 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 */