Commit fcff08de authored by Hiroshi DOYU's avatar Hiroshi DOYU Committed by Tony Lindgren

ARM:OMAP: Integrated blk request queues for mbox fwk

- Taken from maemo.org N800 kernel package.
- Use request queues
- move mbox initialization to late init.
Signed-off-by: default avatarTrilok Soni <soni.trilok@gmail.com>
Signed-off-by: default avatarHiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 6cda72c7
...@@ -156,6 +156,31 @@ static inline void dsp_clk_autoidle(void) ...@@ -156,6 +156,31 @@ static inline void dsp_clk_autoidle(void)
} }
#endif #endif
#if defined(CONFIG_ARCH_OMAP1)
static inline void dsp_clk_enable(void) {}
static inline void dsp_clk_disable(void) {}
#elif defined(CONFIG_ARCH_OMAP2)
static inline void dsp_clk_enable(void)
{
/*XXX should be handled in mach-omap[1,2] XXX*/
PM_PWSTCTRL_DSP = (1 << 18) | (1 << 0);
CM_AUTOIDLE_DSP |= (1 << 1);
CM_CLKSTCTRL_DSP |= (1 << 0);
clk_enable(dsp_fck_handle);
clk_enable(dsp_ick_handle);
__dsp_per_enable();
}
static inline void dsp_clk_disable(void)
{
__dsp_per_disable();
clk_disable(dsp_ick_handle);
clk_disable(dsp_fck_handle);
PM_PWSTCTRL_DSP = (1 << 18) | (3 << 0);
}
#endif
struct dsp_kfunc_device { struct dsp_kfunc_device {
char *name; char *name;
struct clk *fck; struct clk *fck;
......
...@@ -516,14 +516,13 @@ int dsp_late_init(void) ...@@ -516,14 +516,13 @@ int dsp_late_init(void)
{ {
int ret; int ret;
dsp_clk_autoidle(); /*dsp_clk_autoidle();*/
dsp_clk_enable();
#ifdef CONFIG_ARCH_OMAP2
clk_enable(dsp_fck_handle);
clk_enable(dsp_ick_handle);
__dsp_per_enable();
#endif
dsp_mem_late_init(); dsp_mem_late_init();
ret = dsp_mbox_init();
if (ret)
goto fail_mbox;
#ifdef CONFIG_ARCH_OMAP1 #ifdef CONFIG_ARCH_OMAP1
dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE); dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE);
...@@ -531,9 +530,17 @@ int dsp_late_init(void) ...@@ -531,9 +530,17 @@ int dsp_late_init(void)
ret = dsp_kfunc_enable_devices(omap_dsp, ret = dsp_kfunc_enable_devices(omap_dsp,
DSP_KFUNC_DEV_TYPE_COMMON, 0); DSP_KFUNC_DEV_TYPE_COMMON, 0);
if (ret == 0) if (ret == 0)
omap_dsp->enabled = 0; goto fail_kfunc;
omap_dsp->enabled = 1;
return 0; return 0;
fail_kfunc:
dsp_mbox_exit();
fail_mbox:
dsp_clk_disable();
return ret;
} }
extern int dsp_ctl_core_init(void); extern int dsp_ctl_core_init(void);
...@@ -590,13 +597,9 @@ static int __init dsp_drv_probe(struct platform_device *pdev) ...@@ -590,13 +597,9 @@ static int __init dsp_drv_probe(struct platform_device *pdev)
mblog_init(); mblog_init();
if ((ret = dsp_taskmod_init()) < 0) if ((ret = dsp_taskmod_init()) < 0)
goto fail4; goto fail4;
if ((ret = dsp_mbox_init()) < 0)
goto fail5;
return 0; return 0;
fail5:
dsp_taskmod_exit();
fail4: fail4:
mblog_exit(); mblog_exit();
dsp_ctl_exit(); dsp_ctl_exit();
......
...@@ -330,7 +330,7 @@ void mbox_fbctl_upd(void) { } ...@@ -330,7 +330,7 @@ void mbox_fbctl_upd(void) { }
static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count, static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos) loff_t *ppos)
{ {
return __omap_mmu_mem_read(&dsp_mmu, buf, *ppos, count); return __omap_mmu_mem_read(&dsp_mmu, (char __user *)buf, *ppos, count);
} }
static ssize_t dsp_mem_write(struct file *file, const char __user *buf, static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/blkdev.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -36,30 +37,6 @@ ...@@ -36,30 +37,6 @@
static struct omap_mbox *mboxes; static struct omap_mbox *mboxes;
static DEFINE_RWLOCK(mboxes_lock); static DEFINE_RWLOCK(mboxes_lock);
static struct omap_mbox **find_mboxes(const char *name)
{
struct omap_mbox **p;
for (p = &mboxes; *p; p = &(*p)->next) {
if (strcmp((*p)->name, name) == 0)
break;
}
return p;
}
struct omap_mbox *omap_mbox_get(const char *name)
{
struct omap_mbox *mbox;
read_lock(&mboxes_lock);
mbox = *(find_mboxes(name));
read_unlock(&mboxes_lock);
return mbox;
}
EXPORT_SYMBOL(omap_mbox_get);
/* Mailbox Sequence Bit function */ /* Mailbox Sequence Bit function */
void omap_mbox_init_seq(struct omap_mbox *mbox) void omap_mbox_init_seq(struct omap_mbox *mbox)
{ {
...@@ -70,27 +47,18 @@ EXPORT_SYMBOL(omap_mbox_init_seq); ...@@ -70,27 +47,18 @@ EXPORT_SYMBOL(omap_mbox_init_seq);
/* /*
* message sender * message sender
*/ */
int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
{ {
int ret; int ret = 0, i = 1000;
int i = 1000;
static DEFINE_MUTEX(msg_send_lock);
while (mbox_fifo_full(mbox)) { while (mbox_fifo_full(mbox)) {
if (mbox->ops->type == OMAP_MBOX_TYPE2) { if (mbox->ops->type == OMAP_MBOX_TYPE2)
enable_mbox_irq(mbox, IRQ_TX); return -1;
wait_event_interruptible(mbox->tx_waitq,
!mbox_fifo_full(mbox));
} else
udelay(1);
if (--i == 0) if (--i == 0)
return -1; return -1;
udelay(1);
} }
mutex_lock(&msg_send_lock);
if (mbox->msg_sender_cb && arg) { if (mbox->msg_sender_cb && arg) {
ret = mbox->msg_sender_cb(arg); ret = mbox->msg_sender_cb(arg);
if (ret) if (ret)
...@@ -100,9 +68,24 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) ...@@ -100,9 +68,24 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
mbox_seq_toggle(mbox, &msg); mbox_seq_toggle(mbox, &msg);
mbox_fifo_write(mbox, msg); mbox_fifo_write(mbox, msg);
out: out:
mutex_unlock(&msg_send_lock); return ret;
}
return 0; int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
{
struct request *rq;
int ret = 0;
rq = blk_get_request(mbox->txq, WRITE, GFP_ATOMIC);
if (unlikely(!rq)) {
ret = -ENOMEM;
goto fail;
}
rq->data = (void *)msg;
blk_insert_request(mbox->txq, rq, 0, arg);
fail:
return ret;
} }
EXPORT_SYMBOL(omap_mbox_msg_send); EXPORT_SYMBOL(omap_mbox_msg_send);
...@@ -113,24 +96,26 @@ static void mbox_msg_receiver(struct work_struct *work) ...@@ -113,24 +96,26 @@ static void mbox_msg_receiver(struct work_struct *work)
{ {
struct omap_mbox *mbox = struct omap_mbox *mbox =
container_of(work, struct omap_mbox, msg_receive); container_of(work, struct omap_mbox, msg_receive);
struct omap_mbq *mbq = mbox->mbq; struct request_queue *q = mbox->rxq;
struct request *rq;
mbox_msg_t msg; mbox_msg_t msg;
int was_full;
while (!mbq_empty(mbq)) {
was_full = mbq_full(mbq);
msg = mbq_get(mbq);
if (was_full) /* now we have a room in the mbq. */
enable_mbox_irq(mbox, IRQ_RX);
if (unlikely(mbox_seq_test(mbox, msg))) { if (mbox->msg_receive_cb == NULL) {
printk(KERN_ERR sysfs_notify(&mbox->dev.kobj, NULL, "mbox");
"mbox: illegal seq bit! ignoring this command. " return;
"(%08x)\n", msg);
continue;
} }
if (likely(mbox->msg_receive_cb)) while (1) {
rq = elv_next_request(q);
if (!rq)
break;
msg = (mbox_msg_t)rq->data;
blkdev_dequeue_request(rq);
end_that_request_last(rq, 0);
if (mbox->msg_receive_cb)
mbox->msg_receive_cb(msg); mbox->msg_receive_cb(msg);
} }
} }
...@@ -138,39 +123,70 @@ static void mbox_msg_receiver(struct work_struct *work) ...@@ -138,39 +123,70 @@ static void mbox_msg_receiver(struct work_struct *work)
/* /*
* Mailbox interrupt handler * Mailbox interrupt handler
*/ */
static irqreturn_t mbox_interrupt(int irq, void *p) static void mbox_txq_fn(request_queue_t *q)
{ {
mbox_msg_t msg; struct omap_mbox *mbox = q->queuedata;
struct omap_mbox *mbox = (struct omap_mbox *)p; int ret;
struct request *rq;
if (is_mbox_irq(mbox, IRQ_TX)) { while ((rq = elv_next_request(q)) != NULL) {
disable_mbox_irq(mbox, IRQ_TX); ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->data, rq->special);
/* if (ret) {
* NOTE: this doesn't seeem to work as explained in the manual. blk_stop_queue(q);
* IRQSTATUS:NOTFULL can't be cleared even we write 1 to that bit. enable_mbox_irq(mbox, IRQ_TX);
* It is always set when it's not full, regardless of IRQENABLE setting. return;
*/
ack_mbox_irq(mbox, IRQ_TX);
wake_up_interruptible_all(&mbox->tx_waitq);
} }
blkdev_dequeue_request(rq);
end_that_request_last(rq, 0);
}
}
if (!is_mbox_irq(mbox, IRQ_RX)) static void mbox_rxq_fn(request_queue_t *q)
return IRQ_HANDLED; {
struct request *rq;
struct omap_mbox *mbox = q->queuedata;
mbox_msg_t msg;
while (!mbox_fifo_empty(mbox)) { while (!mbox_fifo_empty(mbox)) {
rq = blk_get_request(q, WRITE, GFP_ATOMIC);
if (unlikely(!rq))
goto nomem;
msg = mbox_fifo_read(mbox); msg = mbox_fifo_read(mbox);
if (mbq_add(mbox->mbq, msg)) { /* mbq full */ rq->data = (void *)msg;
disable_mbox_irq(mbox, IRQ_RX);
goto flush_queue; if (unlikely(mbox_seq_test(mbox, msg))) {
pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
if (mbox->err_notify)
mbox->err_notify();
} }
blk_insert_request(mbox->rxq, rq, 0, NULL);
if (mbox->ops->type == OMAP_MBOX_TYPE1) if (mbox->ops->type == OMAP_MBOX_TYPE1)
break; break;
} }
/* no more messages in the fifo. clear IRQ source. */ /* no more messages in the fifo. clear IRQ source. */
ack_mbox_irq(mbox, IRQ_RX); ack_mbox_irq(mbox, IRQ_RX);
flush_queue: enable_mbox_irq(mbox, IRQ_RX);
schedule_work(&mbox->msg_receive); nomem:
queue_work(mbox->workq, &mbox->msg_receive);
}
static irqreturn_t mbox_interrupt(int irq, void *p)
{
struct omap_mbox *mbox = (struct omap_mbox *)p;
if (is_mbox_irq(mbox, IRQ_TX)) {
disable_mbox_irq(mbox, IRQ_TX);
ack_mbox_irq(mbox, IRQ_TX);
blk_start_queue(mbox->txq);
}
if (is_mbox_irq(mbox, IRQ_RX)) {
disable_mbox_irq(mbox, IRQ_RX);
blk_start_queue(mbox->rxq);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -178,32 +194,51 @@ static irqreturn_t mbox_interrupt(int irq, void *p) ...@@ -178,32 +194,51 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
/* /*
* sysfs files * sysfs files
*/ */
static ssize_t mbox_attr_write(struct device *dev, static ssize_t
struct device_attribute *attr, omap_mbox_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char * buf, size_t count)
{ {
int ret; int ret;
mbox_msg_t msg; mbox_msg_t *p = (mbox_msg_t *)buf;
struct omap_mbox *mbox = dev_get_drvdata(dev); struct omap_mbox *mbox = dev_get_drvdata(dev);
msg = (mbox_msg_t) simple_strtoul(buf, NULL, 16); for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) {
ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL);
ret = omap_mbox_msg_send(mbox, msg, NULL);
if (ret) if (ret)
return -1; return -EAGAIN;
p++;
}
return count; return (size_t)((char *)p - buf);
} }
static ssize_t mbox_attr_read(struct device *dev, struct device_attribute *attr, static ssize_t
char *buf) omap_mbox_read(struct device *dev, struct device_attribute *attr,
char * buf)
{ {
struct request *rq;
mbox_msg_t *p = (mbox_msg_t *)buf;
struct omap_mbox *mbox = dev_get_drvdata(dev); struct omap_mbox *mbox = dev_get_drvdata(dev);
struct request_queue *q = mbox->rxq;
return sprintf(buf, mbox->name); while ((rq = elv_next_request(q)) != NULL) {
*p = (mbox_msg_t)rq->data;
blkdev_dequeue_request(rq);
end_that_request_last(rq, 0);
if (unlikely(mbox_seq_test(mbox, *p))) {
pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
continue;
}
p++;
}
pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
return (size_t)((char *)p - buf);
} }
static DEVICE_ATTR(mbox, S_IALLUGO, mbox_attr_read, mbox_attr_write); static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write);
static ssize_t mbox_show(struct class *class, char *buf) static ssize_t mbox_show(struct class *class, char *buf)
{ {
...@@ -213,12 +248,13 @@ static ssize_t mbox_show(struct class *class, char *buf) ...@@ -213,12 +248,13 @@ static ssize_t mbox_show(struct class *class, char *buf)
static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
static struct class omap_mbox_class = { static struct class omap_mbox_class = {
.name = "mbox", .name = "omap_mbox",
}; };
static int omap_mbox_init(struct omap_mbox *mbox) static int omap_mbox_init(struct omap_mbox *mbox)
{ {
int ret; int ret;
request_queue_t *q;
if (likely(mbox->ops->startup)) { if (likely(mbox->ops->startup)) {
ret = mbox->ops->startup(mbox); ret = mbox->ops->startup(mbox);
...@@ -232,58 +268,117 @@ static int omap_mbox_init(struct omap_mbox *mbox) ...@@ -232,58 +268,117 @@ static int omap_mbox_init(struct omap_mbox *mbox)
ret = device_register(&mbox->dev); ret = device_register(&mbox->dev);
if (unlikely(ret)) if (unlikely(ret))
return ret; goto fail_device_reg;
ret = device_create_file(&mbox->dev, &dev_attr_mbox); ret = device_create_file(&mbox->dev, &dev_attr_mbox);
if (unlikely(ret)) { if (unlikely(ret)) {
printk(KERN_ERR printk(KERN_ERR
"device_create_file failed: %d\n", ret); "device_create_file failed: %d\n", ret);
goto fail1; goto fail_create_mbox;
} }
spin_lock_init(&mbox->lock); spin_lock_init(&mbox->lock);
INIT_WORK(&mbox->msg_receive, mbox_msg_receiver); INIT_WORK(&mbox->msg_receive, mbox_msg_receiver);
init_waitqueue_head(&mbox->tx_waitq);
ret = mbq_init(&mbox->mbq);
if (unlikely(ret))
goto fail2;
ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
mbox->name, mbox); mbox->name, mbox);
if (unlikely(ret)) { if (unlikely(ret)) {
printk(KERN_ERR printk(KERN_ERR
"failed to register mailbox interrupt:%d\n", ret); "failed to register mailbox interrupt:%d\n", ret);
goto fail3; goto fail_request_irq;
} }
disable_mbox_irq(mbox, IRQ_RX);
enable_mbox_irq(mbox, IRQ_RX); enable_mbox_irq(mbox, IRQ_RX);
q = blk_init_queue(mbox_txq_fn, &mbox->lock);
if (!q)
goto fail_blkinit_txq;
mbox->txq = q;
q->queuedata = mbox;
q = blk_init_queue(mbox_rxq_fn, &mbox->lock);
if (!q)
goto fail_blkinit_rxq;
mbox->rxq = q;
q->queuedata = mbox;
return 0; return 0;
fail3: fail_blkinit_rxq:
kfree(mbox->mbq); blk_cleanup_queue(mbox->txq);
fail2: fail_blkinit_txq:
class_remove_file(&omap_mbox_class, &class_attr_mbox); free_irq(mbox->irq, mbox);
fail1: fail_request_irq:
class_unregister(&omap_mbox_class); device_remove_file(&mbox->dev, &dev_attr_mbox);
fail_create_mbox:
device_unregister(&mbox->dev);
fail_device_reg:
if (unlikely(mbox->ops->shutdown)) if (unlikely(mbox->ops->shutdown))
mbox->ops->shutdown(mbox); mbox->ops->shutdown(mbox);
return ret; return ret;
} }
static void omap_mbox_shutdown(struct omap_mbox *mbox) static void omap_mbox_fini(struct omap_mbox *mbox)
{ {
blk_cleanup_queue(mbox->txq);
blk_cleanup_queue(mbox->rxq);
flush_workqueue(mbox->workq);
destroy_workqueue(mbox->workq);
free_irq(mbox->irq, mbox); free_irq(mbox->irq, mbox);
kfree(mbox->mbq); device_remove_file(&mbox->dev, &dev_attr_mbox);
class_remove_file(&omap_mbox_class, &class_attr_mbox);
class_unregister(&omap_mbox_class); class_unregister(&omap_mbox_class);
if (unlikely(mbox->ops->shutdown)) if (unlikely(mbox->ops->shutdown))
mbox->ops->shutdown(mbox); mbox->ops->shutdown(mbox);
} }
static struct omap_mbox **find_mboxes(const char *name)
{
struct omap_mbox **p;
for (p = &mboxes; *p; p = &(*p)->next) {
if (strcmp((*p)->name, name) == 0)
break;
}
return p;
}
struct omap_mbox *omap_mbox_get(const char *name)
{
struct omap_mbox *mbox;
char queue_name[MBOX_NAME_LEN];
int ret;
read_lock(&mboxes_lock);
mbox = *(find_mboxes(name));
if (mbox == NULL) {
read_unlock(&mboxes_lock);
return ERR_PTR(-ENOENT);
}
strcpy(queue_name, "mailbox/");
strcat(queue_name, mbox->name);
mbox->workq = create_singlethread_workqueue(queue_name);
read_unlock(&mboxes_lock);
ret = omap_mbox_init(mbox);
if (ret)
return ERR_PTR(-ENODEV);
return mbox;
}
EXPORT_SYMBOL(omap_mbox_get);
void omap_mbox_put(struct omap_mbox *mbox)
{
omap_mbox_fini(mbox);
}
EXPORT_SYMBOL(omap_mbox_put);
int omap_mbox_register(struct omap_mbox *mbox) int omap_mbox_register(struct omap_mbox *mbox)
{ {
int ret = 0; int ret = 0;
...@@ -294,10 +389,6 @@ int omap_mbox_register(struct omap_mbox *mbox) ...@@ -294,10 +389,6 @@ int omap_mbox_register(struct omap_mbox *mbox)
if (mbox->next) if (mbox->next)
return -EBUSY; return -EBUSY;
ret = omap_mbox_init(mbox);
if (ret)
return ret;
write_lock(&mboxes_lock); write_lock(&mboxes_lock);
tmp = find_mboxes(mbox->name); tmp = find_mboxes(mbox->name);
if (*tmp) if (*tmp)
...@@ -321,9 +412,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox) ...@@ -321,9 +412,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
*tmp = mbox->next; *tmp = mbox->next;
mbox->next = NULL; mbox->next = NULL;
write_unlock(&mboxes_lock); write_unlock(&mboxes_lock);
omap_mbox_shutdown(mbox);
return 0; return 0;
} }
tmp = &(*tmp)->next; tmp = &(*tmp)->next;
......
...@@ -12,98 +12,7 @@ ...@@ -12,98 +12,7 @@
#ifndef __ARCH_ARM_PLAT_MAILBOX_H #ifndef __ARCH_ARM_PLAT_MAILBOX_H
#define __ARCH_ARM_PLAT_MAILBOX_H #define __ARCH_ARM_PLAT_MAILBOX_H
/* #define MBOX_NAME_LEN 255
* Mailbox queue handling API
*/
#define MBQ_DEPTH 16
struct omap_mbq {
rwlock_t lock;
mbox_msg_t msg[MBQ_DEPTH];
mbox_msg_t *rp, *wp;
int cnt;
};
static inline int mbq_init(struct omap_mbq **addr)
{
struct omap_mbq *m = kmalloc(sizeof(struct omap_mbq), GFP_KERNEL);
if (!m)
return -ENOMEM;
rwlock_init(&m->lock);
write_lock_irq(&m->lock);
m->rp = m->wp = &m->msg[0];
m->cnt = 0;
write_unlock_irq(&m->lock);
*addr = m;
return 0;
}
static inline int mbq_empty(struct omap_mbq *mbq)
{
int ret;
read_lock_irq(&mbq->lock);
ret = (mbq->cnt == 0);
read_unlock_irq(&mbq->lock);
return ret;
}
static inline int mbq_full(struct omap_mbq *mbq)
{
int ret;
read_lock_irq(&mbq->lock);
ret = (mbq->cnt == MBQ_DEPTH);
read_unlock_irq(&mbq->lock);
return ret;
}
static inline int mbq_add(struct omap_mbq *mbq, mbox_msg_t msg)
{
int ret = 0;
write_lock_irq(&mbq->lock);
*mbq->wp = msg;
if (++mbq->wp == &mbq->msg[MBQ_DEPTH])
mbq->wp = &mbq->msg[0];
if (++mbq->cnt == MBQ_DEPTH) /* full */
ret = -1;
write_unlock_irq(&mbq->lock);
return ret;
}
static inline mbox_msg_t mbq_get(struct omap_mbq *mbq)
{
mbox_msg_t msg;
write_lock_irq(&mbq->lock);
msg = *mbq->rp;
if (++mbq->rp == &mbq->msg[MBQ_DEPTH])
mbq->rp = &mbq->msg[0];
mbq->cnt--;
write_unlock_irq(&mbq->lock);
return msg;
}
static inline void mbq_exit(struct omap_mbq **addr)
{
if (*addr)
kfree(*addr);
}
/* /*
* Mailbox sequence bit API * Mailbox sequence bit API
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/blkdev.h>
typedef u32 mbox_msg_t; typedef u32 mbox_msg_t;
typedef void (mbox_receiver_t)(mbox_msg_t msg); typedef void (mbox_receiver_t)(mbox_msg_t msg);
struct omap_mbox; struct omap_mbox;
struct omap_mbq;
typedef int __bitwise omap_mbox_irq_t; typedef int __bitwise omap_mbox_irq_t;
#define IRQ_TX ((__force omap_mbox_irq_t) 1) #define IRQ_TX ((__force omap_mbox_irq_t) 1)
...@@ -39,30 +39,34 @@ struct omap_mbox { ...@@ -39,30 +39,34 @@ struct omap_mbox {
char *name; char *name;
spinlock_t lock; spinlock_t lock;
unsigned int irq; unsigned int irq;
struct omap_mbox_ops *ops;
wait_queue_head_t tx_waitq;
struct workqueue_struct *workq;
struct work_struct msg_receive; struct work_struct msg_receive;
void (*msg_receive_cb)(mbox_msg_t);
struct omap_mbq *mbq;
request_queue_t *txq, *rxq;
void (*msg_receive_cb)(mbox_msg_t);
int (*msg_sender_cb)(void*); int (*msg_sender_cb)(void*);
struct omap_mbox_ops *ops;
mbox_msg_t seq_snd, seq_rcv; mbox_msg_t seq_snd, seq_rcv;
struct device dev; struct device dev;
struct omap_mbox *next;
void *priv; void *priv;
struct omap_mbox *next; void (*err_notify)(void);
}; };
int omap_mbox_msg_send(struct omap_mbox *mbox_h, mbox_msg_t msg, void* arg); int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg, void *);
void omap_mbox_init_seq(struct omap_mbox *mbox); void omap_mbox_init_seq(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *);
void omap_mbox_put(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *name); int omap_mbox_register(struct omap_mbox *);
int omap_mbox_register(struct omap_mbox *mbox); int omap_mbox_unregister(struct omap_mbox *);
int omap_mbox_unregister(struct omap_mbox *mbox);
#endif /* MAILBOX_H */ #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