fixed flushing mechanism - includes double buffer streams that are also flushed

adding_metadata_to_gr
David Michaeli 2024-02-06 16:04:18 +02:00
rodzic 93b639da58
commit 661c48b198
2 zmienionych plików z 1152 dodań i 1124 usunięć

Wyświetl plik

@ -81,6 +81,10 @@ struct bcm2835_smi_dev_instance
// address related // address related
unsigned int cur_address; unsigned int cur_address;
int address_changed; int address_changed;
// flags
int invalidate_rx_buffers;
int invalidate_tx_buffers;
struct task_struct *reader_thread; struct task_struct *reader_thread;
struct task_struct *writer_thread; struct task_struct *writer_thread;
@ -503,18 +507,12 @@ static long smi_stream_ioctl(struct file *file, unsigned int cmd, unsigned long
} }
break; break;
} }
//------------------------------- //-------------------------------
case SMI_STREAM_IOC_FLUSH_FIFO: case SMI_STREAM_IOC_FLUSH_FIFO:
{ {
if (mutex_lock_interruptible(&inst->read_lock)) // moved to read file operation
{
return -EINTR;
}
kfifo_reset_out(&inst->rx_fifo);
mutex_unlock(&inst->read_lock);
break; break;
} }
//------------------------------- //-------------------------------
default: default:
dev_err(inst->dev, "invalid ioctl cmd: %d", cmd); dev_err(inst->dev, "invalid ioctl cmd: %d", cmd);
@ -569,7 +567,6 @@ static void stream_smi_dma_callback_user_copy(void *param)
{ {
/* Notify the bottom half that a chunk is ready for user copy */ /* Notify the bottom half that a chunk is ready for user copy */
struct bcm2835_smi_instance *inst = (struct bcm2835_smi_instance *)param; struct bcm2835_smi_instance *inst = (struct bcm2835_smi_instance *)param;
up(&inst->bounce.callback_sem); up(&inst->bounce.callback_sem);
} }
@ -604,7 +601,7 @@ ssize_t stream_smi_user_dma( struct bcm2835_smi_instance *inst,
spin_unlock(&inst->transaction_lock); spin_unlock(&inst->transaction_lock);
return 0; return 0;
} }
dma_async_issue_pending(inst->dma_chan); dma_async_issue_pending(inst->dma_chan);
if (dma_dir == DMA_DEV_TO_MEM) if (dma_dir == DMA_DEV_TO_MEM)
@ -785,8 +782,9 @@ int reader_thread_stream_function(void *pv)
{ {
int count = 0; int count = 0;
int current_dma_buffer = 0; int current_dma_buffer = 0;
int buffer_ready[2] = {0, 0}; // does a certain buffer contain actual data
struct bcm2835_smi_bounce_info *bounce = NULL; struct bcm2835_smi_bounce_info *bounce = NULL;
ktime_t start; ktime_t start;
s64 t1, t2, t3; s64 t1, t2, t3;
@ -798,10 +796,22 @@ int reader_thread_stream_function(void *pv)
// check if the streaming state is on, if not, sleep and check again // check if the streaming state is on, if not, sleep and check again
if (inst->state != smi_stream_rx_channel_0 && inst->state != smi_stream_rx_channel_1) if (inst->state != smi_stream_rx_channel_0 && inst->state != smi_stream_rx_channel_1)
{ {
msleep(10); msleep(2);
// invalidate both buffers integrity
buffer_ready[0] = 0;
buffer_ready[1] = 0;
current_dma_buffer = 0;
continue; continue;
} }
if (inst->invalidate_rx_buffers)
{
inst->invalidate_rx_buffers = 0;
buffer_ready[0] = 0;
buffer_ready[1] = 0;
current_dma_buffer = 0;
}
start = ktime_get(); start = ktime_get();
// sync smi address // sync smi address
if (inst->address_changed) if (inst->address_changed)
@ -813,13 +823,14 @@ int reader_thread_stream_function(void *pv)
//-------------------------------------------------------- //--------------------------------------------------------
// try setup a new DMA transfer into dma bounce buffer // try setup a new DMA transfer into dma bounce buffer
// bounce will hold the current transfers state // bounce will hold the current transfers state
buffer_ready[current_dma_buffer] = 0;
count = stream_smi_user_dma(inst->smi_inst, DMA_DEV_TO_MEM, &bounce, current_dma_buffer); count = stream_smi_user_dma(inst->smi_inst, DMA_DEV_TO_MEM, &bounce, current_dma_buffer);
if (count != DMA_BOUNCE_BUFFER_SIZE || bounce == NULL) if (count != DMA_BOUNCE_BUFFER_SIZE || bounce == NULL)
{ {
dev_err(inst->dev, "stream_smi_user_dma returned illegal count = %d, buff_num = %d", count, current_dma_buffer); dev_err(inst->dev, "stream_smi_user_dma returned illegal count = %d, buff_num = %d", count, current_dma_buffer);
spin_lock(&inst->smi_inst->transaction_lock); //spin_lock(&inst->smi_inst->transaction_lock);
dmaengine_terminate_all(inst->smi_inst->dma_chan); //dmaengine_terminate_all(inst->smi_inst->dma_chan);
spin_unlock(&inst->smi_inst->transaction_lock); //spin_unlock(&inst->smi_inst->transaction_lock);
continue; continue;
} }
@ -827,20 +838,25 @@ int reader_thread_stream_function(void *pv)
//-------------------------------------------------------- //--------------------------------------------------------
// Don't wait for the buffer to fill in, copy the "other" // Don't wait for the buffer to fill in, copy the "other"
// previously filled up buffer into the kfifo // previously filled up buffer into the kfifo - only if
if (mutex_lock_interruptible(&inst->read_lock)) // buffer is valid
{
return -EINTR;
}
start = ktime_get(); start = ktime_get();
kfifo_in(&inst->rx_fifo, bounce->buffer[1-current_dma_buffer], DMA_BOUNCE_BUFFER_SIZE); if (buffer_ready[1-current_dma_buffer])
mutex_unlock(&inst->read_lock); {
if (mutex_lock_interruptible(&inst->read_lock))
// for the polling mechanism {
inst->readable = true; //return -EINTR;
wake_up_interruptible(&inst->poll_event); continue;
}
kfifo_in(&inst->rx_fifo, bounce->buffer[1-current_dma_buffer], DMA_BOUNCE_BUFFER_SIZE);
mutex_unlock(&inst->read_lock);
// for the polling mechanism
inst->readable = true;
wake_up_interruptible(&inst->poll_event);
}
t2 = ktime_to_ns(ktime_sub(ktime_get(), start)); t2 = ktime_to_ns(ktime_sub(ktime_get(), start));
@ -866,13 +882,14 @@ int reader_thread_stream_function(void *pv)
if (inst->state == smi_stream_idle) if (inst->state == smi_stream_idle)
{ {
dev_info(inst->dev, "Reader state became idle, terminating dma"); dev_info(inst->dev, "Reader state became idle, terminating dma");
spin_lock(&inst->smi_inst->transaction_lock); //spin_lock(&inst->smi_inst->transaction_lock);
dmaengine_terminate_all(inst->smi_inst->dma_chan); //dmaengine_terminate_all(inst->smi_inst->dma_chan);
spin_unlock(&inst->smi_inst->transaction_lock); //spin_unlock(&inst->smi_inst->transaction_lock);
} }
//-------------------------------------------------------- //--------------------------------------------------------
// Switch the buffers // Switch the buffers
buffer_ready[current_dma_buffer] = 1;
current_dma_buffer = 1-current_dma_buffer; current_dma_buffer = 1-current_dma_buffer;
} }
inst->reader_waiting_sema = false; inst->reader_waiting_sema = false;
@ -1091,17 +1108,28 @@ static int smi_stream_release(struct inode *inode, struct file *file)
static ssize_t smi_stream_read_file_fifo(struct file *file, char __user *buf, size_t count, loff_t *ppos) static ssize_t smi_stream_read_file_fifo(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{ {
int ret = 0; int ret = 0;
unsigned int copied; unsigned int copied = 0;
size_t num_bytes = 0;
unsigned int count_actual = count;
if (mutex_lock_interruptible(&inst->read_lock)) if (buf == NULL)
{ {
return -EINTR; //dev_info(inst->dev, "Flushing internal rx_kfifo");
} if (mutex_lock_interruptible(&inst->read_lock))
ret = kfifo_to_user(&inst->rx_fifo, buf, count, &copied); {
mutex_unlock(&inst->read_lock); return -EINTR;
}
kfifo_reset_out(&inst->rx_fifo);
mutex_unlock(&inst->read_lock);
inst->invalidate_rx_buffers = 1;
}
else
{
if (mutex_lock_interruptible(&inst->read_lock))
{
return -EINTR;
}
ret = kfifo_to_user(&inst->rx_fifo, buf, count, &copied);
mutex_unlock(&inst->read_lock);
}
return ret < 0 ? ret : (ssize_t)copied; return ret < 0 ? ret : (ssize_t)copied;
} }
@ -1348,6 +1376,8 @@ static int smi_stream_dev_probe(struct platform_device *pdev)
// Streaming instance initializations // Streaming instance initializations
inst->reader_thread = NULL; inst->reader_thread = NULL;
inst->writer_thread = NULL; inst->writer_thread = NULL;
inst->invalidate_rx_buffers = 0;
inst->invalidate_tx_buffers = 0;
init_waitqueue_head(&inst->poll_event); init_waitqueue_head(&inst->poll_event);
inst->readable = false; inst->readable = false;
inst->writeable = false; inst->writeable = false;