Commit 9de93068 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Fix pointer convertion error in jpeghead

WIP: hw pointer offset error is still there
parent 2fd99c36
......@@ -184,8 +184,8 @@ loff_t circbuf_all_lseek(struct file *file, loff_t offset, int orig)
return circbuf_lseek(file, offset, orig);
case JPEGHEAD_MINOR:
if (orig == SEEK_END && offset > 0) {
rp = BYTE2DW(offset) & (~7); // convert to index to long, align to 32-bytes
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[X393_BUFFSUB(rp, 8)];
rp = BYTE2DW(X393_BUFFSUB(offset, CHUNK_SIZE)) & (~7); // convert to index to long, align to 32-bytes
fp = (struct interframe_params_t *) &circbuf_priv[chn].buf_ptr[rp];
}
return jpeghead_lseek(file, offset, orig, fp);
case HUFFMAN_MINOR:
......
......@@ -310,6 +310,38 @@ static ssize_t sync_for_device_bidir(struct device *dev, struct device_attribute
return count;
}
static ssize_t flush_cpu_cache(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
const int buff_size = 0x1000000;
const int buff_start_offset = 0x100000;
unsigned int chn;
int start_offset, end_offset;
int num_items;
dma_addr_t phys_addr_start, phys_addr_end;
num_items = sscanf(buf, "%u:%d:%d", &chn, &start_offset, &end_offset);
if (num_items == 3) {
// invalidate L2 caches
if (end_offset > start_offset) {
// handle single buffer case
phys_addr_start = _elphel_buf.paddr + buff_start_offset + chn * buff_size + start_offset;
phys_addr_end = _elphel_buf.paddr + buff_start_offset + chn * buff_size + end_offset - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
} else {
// handle split buffer case when pointer rolls over the end
// first, process the peace at the end of the buffer
phys_addr_start = _elphel_buf.paddr + buff_start_offset + chn * buff_size + start_offset;
phys_addr_end = _elphel_buf.paddr + buff_start_offset + ++chn * buff_size - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
// second, process the peace at the start of the buffer
phys_addr_start = _elphel_buf.paddr + buff_start_offset + chn * buff_size;
phys_addr_end = _elphel_buf.paddr + buff_start_offset + chn * buff_size + end_offset - 1;
outer_inv_range(phys_addr_start, phys_addr_end);
}
}
return count;
}
static ssize_t get_sync_for_device_h2d(struct device *dev, struct device_attribute *attr, char *buf)
{
......@@ -335,6 +367,11 @@ static ssize_t get_sync_for_cpu_bidir(struct device *dev, struct device_attribut
{
return sprintf(buf,"Write address/length pair into this file to hand this region of the bidirectional DMA buffer to CPU (before CPU reads).\n");
}
static ssize_t get_flush_cpu_cache(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "Write command and address into this file to flush CPU caches. Format 'chn:start_offset:end_offset' where "
"'chn' is sensor channel, 'start_offset' and 'end_offset' are start and end data offsets in circbuf\n");
}
static DEVICE_ATTR(buffer_address, SYSFS_PERMISSIONS & SYSFS_READONLY, get_paddr, NULL);
static DEVICE_ATTR(buffer_pages, SYSFS_PERMISSIONS & SYSFS_READONLY, get_size, NULL);
......@@ -351,6 +388,7 @@ static DEVICE_ATTR(sync_for_cpu_d2h, SYSFS_PERMISSIONS,
static DEVICE_ATTR(sync_for_device_d2h, SYSFS_PERMISSIONS, get_sync_for_device_d2h, sync_for_device_d2h);
static DEVICE_ATTR(sync_for_cpu_bidir, SYSFS_PERMISSIONS, get_sync_for_cpu_bidir, sync_for_cpu_bidir);
static DEVICE_ATTR(sync_for_device_bidir, SYSFS_PERMISSIONS, get_sync_for_device_bidir, sync_for_device_bidir);
static DEVICE_ATTR(flush_cpu_cache, SYSFS_PERMISSIONS, get_flush_cpu_cache, flush_cpu_cache);
static struct attribute *root_dev_attrs[] = {
&dev_attr_buffer_address.attr,
......@@ -368,6 +406,7 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_sync_for_device_d2h.attr,
&dev_attr_sync_for_cpu_bidir.attr,
&dev_attr_sync_for_device_bidir.attr,
&dev_attr_flush_cpu_cache.attr,
NULL
};
......
......@@ -244,6 +244,7 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
{
phys_addr_t phys_addr;
void *virt_addr;
int prev_dword;
int xferred; /// number of 32-byte chunks transferred since compressor was reset
x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num);
......@@ -268,11 +269,31 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
* end of buffer and 32 zero bytes start from the beginning of the buffer. HW pointer in this case should
* be 0x20, but it is 0x00 in fact. Try to detect this situation and correct the offset.
*/
if (jptr->jpeg_wp == 0 &&
circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] == 0x00 &&
(circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp - 1] & MARKER_FF) == MARKER_FF) {
jptr->jpeg_wp += INTERFRAME_PARAMS_SZ;
corrected_offset[jptr->chn_num] += 1;
if (jptr->jpeg_wp == 0) {
// if pointer is set incorrectly, then we need two invalidate two cache lines in order to
// estimate the situation correctly: one line after the pointer, which should be the line of
// 32 zeros, and one line before the pointer, which should be the last line of the frame. If this is not done
// then the data read from memory can be incorrect and error detection will give false result. Barrier is set to
// prevent compiler from reordering operations.
phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr;
virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr;
dev_dbg(NULL, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
__cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
phys_addr = circbuf_priv_ptr[jptr->chn_num].phys_addr + CCAM_DMA_SIZE - CHUNK_SIZE;
virt_addr = circbuf_priv_ptr[jptr->chn_num].buf_ptr + BYTE2DW(CCAM_DMA_SIZE - CHUNK_SIZE);
outer_inv_range(phys_addr, phys_addr + (CHUNK_SIZE - 1));
__cpuc_flush_dcache_area(virt_addr, CHUNK_SIZE);
dev_dbg(NULL, "from updateIRQJPEG_wp: phys_addr = 0x%x, virt_addr = 0x%p\n", phys_addr, virt_addr);
barrier();
prev_dword = X393_BUFFSUB(DW2BYTE(jptr->jpeg_wp), 4);
dev_dbg(NULL, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp]);
dev_dbg(NULL, "circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] = 0x%x\n", circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)]);
if (circbuf_priv_ptr[jptr->chn_num].buf_ptr[jptr->jpeg_wp] == 0x00 &&
(circbuf_priv_ptr[jptr->chn_num].buf_ptr[BYTE2DW(prev_dword)] & MARKER_FF) == MARKER_FF) {
jptr->jpeg_wp += INTERFRAME_PARAMS_SZ;
corrected_offset[jptr->chn_num] += 1;
}
}
// invalidate CPU L1 and L2 caches
......
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