From 57e77f7daf1ac886d81236fab9c5d492078aedef Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 24 Sep 2013 18:27:34 +0800 Subject: [PATCH] ENGR00280852-4 mxc: asrc: Use completion instead of counter Use completion instead of counter to make driver clean and drop implicit mdelay by using wait_for_completion(). Signed-off-by: Nicolin Chen --- drivers/mxc/asrc/mxc_asrc.c | 79 ++++++++++++++----------------------- include/linux/mxc_asrc.h | 7 ++-- 2 files changed, 32 insertions(+), 54 deletions(-) diff --git a/drivers/mxc/asrc/mxc_asrc.c b/drivers/mxc/asrc/mxc_asrc.c index 5ae42217b77c..d17afdc27ddf 100644 --- a/drivers/mxc/asrc/mxc_asrc.c +++ b/drivers/mxc/asrc/mxc_asrc.c @@ -48,8 +48,6 @@ DEFINE_SPINLOCK(data_lock); DEFINE_SPINLOCK(pair_lock); -DEFINE_SPINLOCK(input_int_lock); -DEFINE_SPINLOCK(output_int_lock); /* Sample rates are aligned with that defined in pcm.h file */ static const unsigned char asrc_process_table[][8][2] = { @@ -721,17 +719,11 @@ static int mxc_init_asrc(void) static void asrc_input_dma_callback(void *data) { struct asrc_pair_params *params = (struct asrc_pair_params *)data; - unsigned long lock_flags; dma_unmap_sg(NULL, params->input_sg, params->input_sg_nodes, DMA_MEM_TO_DEV); - spin_lock_irqsave(&input_int_lock, lock_flags); - - params->input_counter++; - wake_up_interruptible(¶ms->input_wait_queue); - - spin_unlock_irqrestore(&input_int_lock, lock_flags); + complete(¶ms->input_complete); schedule_work(¶ms->task_output_work); @@ -744,6 +736,8 @@ static void asrc_output_dma_callback(void *data) dma_unmap_sg(NULL, params->output_sg, params->output_sg_nodes, DMA_MEM_TO_DEV); + + complete(¶ms->output_complete); } static unsigned int asrc_get_output_FIFO_size(enum asrc_pair_index index) @@ -787,18 +781,14 @@ static void asrc_read_output_FIFO(struct asrc_pair_params *params) u32 *reg24 = params->output_last_period.dma_vaddr; u16 *reg16 = params->output_last_period.dma_vaddr; enum asrc_pair_index index = params->index; - u32 d, i, j, reg, size, t_size; + u32 i, j, reg, size, t_size; bool bit24 = false; if (params->output_word_width == ASRC_WIDTH_24_BIT) bit24 = true; - /* Delay for last period data output */ - d = 1000000 / params->output_sample_rate * params->last_period_sample; - t_size = 0; do { - mdelay(1); size = asrc_get_output_FIFO_size(index); for (i = 0; i < size; i++) { for (j = 0; j < params->channel_nums; j++) { @@ -832,17 +822,19 @@ static void asrc_output_task_worker(struct work_struct *w) if (!params->pair_hold) return; + if (!wait_for_completion_interruptible_timeout(¶ms->output_complete, HZ)) { + dev_err(asrc->dev, "output dma callback timeout for Pair %c\n", + 'A' + params->index); + return; + } + + init_completion(¶ms->output_complete); + spin_lock_irqsave(&pair_lock, lock_flags); asrc_read_output_FIFO(params); spin_unlock_irqrestore(&pair_lock, lock_flags); - /* Finish receiving all output data */ - spin_lock_irqsave(&output_int_lock, lock_flags); - - params->output_counter++; - wake_up_interruptible(¶ms->output_wait_queue); - - spin_unlock_irqrestore(&output_int_lock, lock_flags); + complete(¶ms->lastperiod_complete); } static void mxc_free_dma_buf(struct asrc_pair_params *params) @@ -1104,42 +1096,34 @@ int mxc_asrc_process_io_buffer(struct asrc_pair_params *params, { void *last_vaddr = params->output_last_period.dma_vaddr; unsigned int *last_len = ¶ms->output_last_period.length; - unsigned int *counter, dma_len, *buf_len; - unsigned long lock_flags; + unsigned int dma_len, *buf_len; + struct completion *complete; void __user *buf_vaddr; void *dma_vaddr; - wait_queue_head_t *q; - spinlock_t *lock; if (in) { dma_vaddr = params->input_dma_total.dma_vaddr; dma_len = params->input_dma_total.length; - q = ¶ms->input_wait_queue; - counter = ¶ms->input_counter; buf_len = &pbuf->input_buffer_length; - lock = &input_int_lock; + complete = ¶ms->input_complete; buf_vaddr = (void __user *)pbuf->input_buffer_vaddr; } else { dma_vaddr = params->output_dma_total.dma_vaddr; dma_len = params->output_dma_total.length; - q = ¶ms->output_wait_queue; - counter = ¶ms->output_counter; buf_len = &pbuf->output_buffer_length; - lock = &output_int_lock; + complete = ¶ms->lastperiod_complete; buf_vaddr = (void __user *)pbuf->output_buffer_vaddr; } - if (!wait_event_interruptible_timeout(*q, *counter != 0, 10 * HZ)) { - dev_err(asrc->dev, "ASRC_DQ_OUTBUF timeout counter %x\n", *counter); + if (!wait_for_completion_interruptible_timeout(complete, 10 * HZ)) { + dev_err(asrc->dev, "ASRC_DQ_OUTBUF timeout\n"); return -ETIME; } else if (signal_pending(current)) { dev_err(asrc->dev, "ASRC_DQ_INBUF interrupt received.\n"); return -ERESTARTSYS; } - spin_lock_irqsave(lock, lock_flags); - (*counter)--; - spin_unlock_irqrestore(lock, lock_flags); + init_completion(complete); *buf_len = dma_len; @@ -1325,8 +1309,9 @@ static long asrc_ioctl_config_pair(struct asrc_pair_params *params, return -EBUSY; } - init_waitqueue_head(¶ms->input_wait_queue); - init_waitqueue_head(¶ms->output_wait_queue); + init_completion(¶ms->input_complete); + init_completion(¶ms->output_complete); + init_completion(¶ms->lastperiod_complete); /* Add work struct to receive last period of output data */ INIT_WORK(¶ms->task_output_work, asrc_output_task_worker); @@ -1475,17 +1460,10 @@ static long asrc_ioctl_flush(struct asrc_pair_params *params, void __user *user) { enum asrc_pair_index index = params->index; - unsigned long lock_flags; - - /* Flush input dma buffer */ - spin_lock_irqsave(&input_int_lock, lock_flags); - params->input_counter = 0; - spin_unlock_irqrestore(&input_int_lock, lock_flags); - /* Flush output dma buffer */ - spin_lock_irqsave(&output_int_lock, lock_flags); - params->output_counter = 0; - spin_unlock_irqrestore(&output_int_lock, lock_flags); + init_completion(¶ms->input_complete); + init_completion(¶ms->output_complete); + init_completion(¶ms->lastperiod_complete); /* Release DMA and request again */ dma_release_channel(params->input_dma_channel); @@ -1589,8 +1567,9 @@ static int mxc_asrc_close(struct inode *inode, struct file *file) asrc_stop_conv(pair_params->index); - wake_up_interruptible(&pair_params->input_wait_queue); - wake_up_interruptible(&pair_params->output_wait_queue); + complete(&pair_params->input_complete); + complete(&pair_params->output_complete); + complete(&pair_params->lastperiod_complete); } if (pair_params->pair_hold) { spin_lock_irqsave(&pair_lock, lock_flags); diff --git a/include/linux/mxc_asrc.h b/include/linux/mxc_asrc.h index ecee963193af..778a1753fbe7 100644 --- a/include/linux/mxc_asrc.h +++ b/include/linux/mxc_asrc.h @@ -313,10 +313,9 @@ struct asrc_p2p_params { struct asrc_pair_params { enum asrc_pair_index index; - wait_queue_head_t input_wait_queue; - wait_queue_head_t output_wait_queue; - unsigned int input_counter; - unsigned int output_counter; + struct completion input_complete; + struct completion output_complete; + struct completion lastperiod_complete; struct dma_chan *input_dma_channel; struct dma_chan *output_dma_channel; unsigned int input_buffer_size; -- 2.39.5