]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: DSPGW: Fix deadlock
authorHiroshi DOYU <Hiroshi.DOYU@nokia.com>
Thu, 21 Sep 2006 14:41:45 +0000 (17:41 +0300)
committerJuha Yrjola <juha.yrjola@solidboot.com>
Thu, 21 Sep 2006 15:45:59 +0000 (18:45 +0300)
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
arch/arm/plat-omap/dsp/dsp_core.c
include/asm-arm/arch-omap/mailbox.h

index 76a9383a80d289799d5cb3d0ac616bd57e9ba31d..09c0388bdce5c08c60bda78d9b38ace1c1545b1c 100644 (file)
@@ -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);
index e72be75c16595874dd8bb5b534a697e078e3e0b1..66669f07b95b65b3915f8625c8243522c676136b 100644 (file)
@@ -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 */