From ca8c5584e07a5ca2702ef6be79ba2e5be0769f2e Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 22:59:44 +0100 Subject: [PATCH] facetimehd: add channel waitqueue add a per channel waitqueue to be able to have more than one ringbuffer entry in flight. Signed-off-by: Sven Schnelle --- fthd_drv.c | 27 +++++++++++++++------------ fthd_drv.h | 8 ++------ fthd_isp.c | 12 +++--------- fthd_ringbuf.c | 26 +++++++++++++------------- fthd_ringbuf.h | 1 + fthd_v4l2.c | 24 +----------------------- 6 files changed, 35 insertions(+), 63 deletions(-) diff --git a/fthd_drv.c b/fthd_drv.c index 4a6b7e6..f47517b 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -190,18 +190,26 @@ static void io_t2h_handler(struct fthd_private *dev_priv, } -static void buf_h2t_handler(struct fthd_private *dev_priv, - struct fw_channel *chan, - u32 entry) -{ - fthd_buffer_queued_handler(dev_priv, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & ~3); -} - static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *chan) { u32 entry; int ret; + if (chan == dev_priv->channel_io) { + pr_debug("IO channel ready\n"); + wake_up_interruptible(&chan->wq); + return; + } + + if (chan == dev_priv->channel_buf_h2t) { + pr_debug("H2T channel ready\n"); + wake_up_interruptible(&chan->wq); + return; + } + + if (chan == dev_priv->channel_debug) + return; + while((entry = fthd_channel_ringbuf_receive(dev_priv, chan)) != (u32)-1) { pr_debug("channel %s: message available, address %08x\n", chan->name, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS)); if (chan == dev_priv->channel_shared_malloc) { @@ -213,12 +221,8 @@ static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *ch pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); } else if (chan == dev_priv->channel_buf_t2h) { buf_t2h_handler(dev_priv, chan, entry); - } else if (chan == dev_priv->channel_io) { - wake_up_interruptible(&dev_priv->cmd_wq); } else if (chan == dev_priv->channel_io_t2h) { io_t2h_handler(dev_priv, chan, entry); - } else if (chan == dev_priv->channel_buf_h2t) { - buf_h2t_handler(dev_priv, chan, entry); } } } @@ -456,7 +460,6 @@ static int fthd_pci_probe(struct pci_dev *pdev, mutex_init(&dev_priv->vb2_queue_lock); mutex_init(&dev_priv->ioctl_lock); - init_waitqueue_head(&dev_priv->cmd_wq); INIT_LIST_HEAD(&dev_priv->buffer_queue); INIT_WORK(&dev_priv->irq_work, fthd_irq_work); diff --git a/fthd_drv.h b/fthd_drv.h index f967cf1..41050c2 100644 --- a/fthd_drv.h +++ b/fthd_drv.h @@ -56,11 +56,10 @@ struct fw_channel { u32 size; u32 source; u32 type; - int tx_lock; - int rx_lock; struct fthd_ringbuf ringbuf; spinlock_t lock; - + /* waitqueue for signaling completion */ + wait_queue_head_t wq; char *name; }; @@ -75,9 +74,6 @@ struct fthd_private { /* lock for synchronizing with irq/workqueue */ spinlock_t io_lock; - /* waitqueue for signaling command completion */ - wait_queue_head_t cmd_wq; - /* Mapped PCI resources */ void __iomem *s2_io; u32 s2_io_len; diff --git a/fthd_isp.c b/fthd_isp.c index fece39e..6af25cb 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -236,11 +236,8 @@ static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int chan->source = info.source; chan->size = info.size; chan->offset = info.offset; - if (chan->type == FW_CHAN_TYPE_OUT) - chan->rx_lock = 1; - if (chan->type == FW_CHAN_TYPE_IN) - chan->tx_lock = 1; spin_lock_init(&chan->lock); + init_waitqueue_head(&chan->wq); } dev_priv->channel_terminal = isp_get_chan_index(dev_priv, "TERMINAL"); @@ -312,13 +309,10 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman goto out; } - if (wait_event_interruptible_timeout(dev_priv->cmd_wq, - FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1, HZ) <= 0) { - dev_err(&dev_priv->pdev->dev, "timeout wait for command %d\n", cmd.opcode); - fthd_channel_ringbuf_dump(dev_priv, dev_priv->channel_io); + ret = fthd_channel_wait_ready(dev_priv, dev_priv->channel_io, entry, 2000); + if (ret) { if (response_len) *response_len = 0; - ret = -ETIMEDOUT; goto out; } diff --git a/fthd_ringbuf.c b/fthd_ringbuf.c index f77de0c..6097dc2 100644 --- a/fthd_ringbuf.c +++ b/fthd_ringbuf.c @@ -86,12 +86,7 @@ int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * spin_lock_irq(&chan->lock); entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx); - if (chan->tx_lock) { - spin_unlock_irq(&chan->lock); - return -EBUSY; - } - - if (chan->type != FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) + if (++chan->ringbuf.idx >= chan->size) chan->ringbuf.idx = 0; if (!(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0)) { @@ -99,9 +94,6 @@ int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * return -EAGAIN; } - chan->tx_lock = 1; - chan->rx_lock = 0; - FTHD_S2_MEM_WRITE(request_size, entry + FTHD_RINGBUF_REQUEST_SIZE); FTHD_S2_MEM_WRITE(response_size, entry + FTHD_RINGBUF_RESPONSE_SIZE); wmb(); @@ -123,8 +115,6 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, u32 entry, ret = (u32)-1; spin_lock_irq(&chan->lock); - if (chan->rx_lock) - goto out; entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx); @@ -137,9 +127,19 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, if (chan->type == FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) chan->ringbuf.idx = 0; - chan->rx_lock = 1; - chan->tx_lock = 0; out: spin_unlock_irq(&chan->lock); return ret; } + +int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout) +{ + if (wait_event_interruptible_timeout(chan->wq, + (FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0), + msecs_to_jiffies(timeout)) <= 0) { + dev_err(&dev_priv->pdev->dev, "%s: timeout\n", chan->name); + fthd_channel_ringbuf_dump(dev_priv, chan); + return -ETIMEDOUT; + } + return 0; +} diff --git a/fthd_ringbuf.h b/fthd_ringbuf.h index ffe0625..3b75610 100644 --- a/fthd_ringbuf.h +++ b/fthd_ringbuf.h @@ -48,4 +48,5 @@ extern int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_ch extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, struct fw_channel *chan); +extern int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout); #endif diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 5050a1d..f7c909e 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -137,29 +137,7 @@ static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ct pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); return ret; } - - if (wait_event_interruptible_timeout(ctx->wq, ctx->done, HZ) <= 0) { - dev_err(&dev_priv->pdev->dev, "timeout wait for buffer %p\n", ctx->vb); - return -ETIMEDOUT; - } - ctx->done = 0; - return 0; -} - -void fthd_buffer_queued_handler(struct fthd_private *dev_priv, u32 offset) -{ - - struct dma_descriptor_list list; - struct h2t_buf_ctx *ctx; - - - FTHD_S2_MEMCPY_FROMIO(&list, offset, sizeof(list)); - - ctx = (struct h2t_buf_ctx *)list.desc[0].tag; - pr_debug("vb %p, ctx = %p\n", ctx->vb, ctx); - memcpy(&ctx->dma_desc_list, &list, sizeof(ctx->dma_desc_list)); - ctx->done = 1; - wake_up_interruptible(&ctx->wq); + return fthd_channel_wait_ready(dev_priv, dev_priv->channel_buf_h2t, entry, 2000); } static void fthd_buffer_queue(struct vb2_buffer *vb)