Commit 33ec5861 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Prepare data rate measurements

A maximum of length of 4Mb may exist for PRDT entry - this should be
fixed in driver.
parent 4ee3713c
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "../elphel/exifa.h" #include "../elphel/exifa.h"
#include "../elphel/jpeghead.h" #include "../elphel/jpeghead.h"
//#include "../elphel/circbuf.h" //#include "../elphel/circbuf.h"
#include "../elphel/x393_helpers.h"
#include <elphel/elphel393-mem.h> #include <elphel/elphel393-mem.h>
...@@ -132,16 +133,16 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance) ...@@ -132,16 +133,16 @@ static irqreturn_t elphel_irq_handler(int irq, void * dev_instance)
dpriv->flags &= ~IRQ_SIMPLE; dpriv->flags &= ~IRQ_SIMPLE;
irq_stat = readl(port_mmio + PORT_IRQ_STAT); irq_stat = readl(port_mmio + PORT_IRQ_STAT);
printk(KERN_DEBUG "irq_stat = 0x%x, host irq_stat = 0x%x\n", irq_stat, host_irq_stat); dev_dbg(host->dev, "irq_stat = 0x%x, host irq_stat = 0x%x\n", irq_stat, host_irq_stat);
// writel(irq_stat, port_mmio + PORT_IRQ_STAT); writel(irq_stat, port_mmio + PORT_IRQ_STAT);
writel(0xffffffff, port_mmio + PORT_IRQ_STAT); // writel(0xffffffff, port_mmio + PORT_IRQ_STAT);
writel(host_irq_stat, hpriv->mmio + HOST_IRQ_STAT); writel(host_irq_stat, hpriv->mmio + HOST_IRQ_STAT);
handled = IRQ_HANDLED; handled = IRQ_HANDLED;
if (process_cmd(host->dev, dpriv, host->ports[0]) == 0) // if (process_cmd(host->dev, dpriv, host->ports[0]) == 0)
finish_cmd(host->dev, dpriv); // finish_cmd(host->dev, dpriv);
} else { } else {
/* pass handling to AHCI level */ /* pass handling to AHCI level */
handled = ahci_single_irq_intr(irq, dev_instance); handled = ahci_single_irq_intr(irq, dev_instance);
...@@ -401,6 +402,16 @@ static void elphel_qc_prep(struct ata_queued_cmd *qc) ...@@ -401,6 +402,16 @@ static void elphel_qc_prep(struct ata_queued_cmd *qc)
unsigned char app15[ALIGNMENT_SIZE] = {0xff, 0xef}; unsigned char app15[ALIGNMENT_SIZE] = {0xff, 0xef};
/* used for performance measurements */
struct time_mark {
uint32_t size;
uint32_t usec;
uint32_t sec;
};
struct time_mark prev_mark;
struct time_mark curr_mark;
uint32_t total_datarate;
/* this should be placed to system includes directory*/ /* this should be placed to system includes directory*/
#define DRV_CMD_WRITE 0 #define DRV_CMD_WRITE 0
#define DRV_CMD_FINISH 1 #define DRV_CMD_FINISH 1
...@@ -592,11 +603,16 @@ static ssize_t hdr_write(struct device *dev, struct device_attribute *attr, cons ...@@ -592,11 +603,16 @@ static ssize_t hdr_write(struct device *dev, struct device_attribute *attr, cons
return buff_sz; return buff_sz;
} }
static ssize_t datarate_read(struct device *dev, struct device_attribute *attr, char *buff)
{
return sprintf(buff, "Total data rate: %u Mb/s\n", total_datarate);
}
static DEVICE_ATTR(data_0_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_0_write); static DEVICE_ATTR(data_0_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_0_write);
static DEVICE_ATTR(data_1_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_1_write); static DEVICE_ATTR(data_1_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_1_write);
static DEVICE_ATTR(data_proc, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_write); static DEVICE_ATTR(data_proc, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, data_write);
static DEVICE_ATTR(exif_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, exif_write); static DEVICE_ATTR(exif_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, exif_write);
static DEVICE_ATTR(jpg_hdr_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, hdr_write); static DEVICE_ATTR(jpg_hdr_sz, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, NULL, hdr_write);
static DEVICE_ATTR(datarate_mbs, S_IRUSR | S_IRGRP, datarate_read, NULL);
/* End of debug functions*/ /* End of debug functions*/
/** Map buffer vectors to S/G list and return the number of vectors mapped */ /** Map buffer vectors to S/G list and return the number of vectors mapped */
...@@ -635,7 +651,6 @@ static int map_vectors(struct elphel_ahci_priv *dpriv) ...@@ -635,7 +651,6 @@ static int map_vectors(struct elphel_ahci_priv *dpriv)
dpriv->curr_data_offset = chunks[i].iov_len; dpriv->curr_data_offset = chunks[i].iov_len;
finish = 1; finish = 1;
} }
printk(KERN_DEBUG "mapping data chunk number %d: total_sz = %u, vect.iov_len = %u\n", i, total_sz, vect.iov_len);
if (vect.iov_len != 0) { if (vect.iov_len != 0) {
dpriv->sgl[index++] = vect; dpriv->sgl[index++] = vect;
} }
...@@ -1180,6 +1195,22 @@ static void finish_rec(struct device *dev, struct elphel_ahci_priv *dpriv, struc ...@@ -1180,6 +1195,22 @@ static void finish_rec(struct device *dev, struct elphel_ahci_priv *dpriv, struc
process_cmd(dev, dpriv, port); process_cmd(dev, dpriv, port);
} }
/** Return time difference in microseconds between two time stamps */
#define USEC 1000000
static uint32_t timediff(struct time_mark *start, struct time_mark *end)
{
uint32_t ret = 0;
if (end->sec >= start->sec) {
if (end->usec >= start->usec) {
ret = USEC * (end->sec - start->sec) + (end->usec - start->usec);
} else {
ret = USEC * (end->sec - start->sec - 1) + (USEC + end->usec - start->usec);
}
}
return ret;
}
static ssize_t rawdev_write(struct device *dev, ///< static ssize_t rawdev_write(struct device *dev, ///<
struct device_attribute *attr, ///< struct device_attribute *attr, ///<
const char *buff, ///< const char *buff, ///<
...@@ -1203,9 +1234,11 @@ static ssize_t rawdev_write(struct device *dev, ///< ...@@ -1203,9 +1234,11 @@ static ssize_t rawdev_write(struct device *dev, ///<
size_t blocks_num; size_t blocks_num;
static int dont_process = 0; static int dont_process = 0;
if ((dpriv->flags & PROC_CMD) || dont_process) if ((dpriv->flags & PROC_CMD) || dont_process) {
// we are not ready yet // we are not ready yet
printk(KERN_DEBUG ">>> not ready: flags = %u\n", dpriv->flags);
return -EAGAIN; return -EAGAIN;
}
if (buff_sz != sizeof(struct frame_data)) { if (buff_sz != sizeof(struct frame_data)) {
dev_err(dev, "the size of the data buffer is incorrect, should be equal to sizeof(struct frame_data)\n"); dev_err(dev, "the size of the data buffer is incorrect, should be equal to sizeof(struct frame_data)\n");
...@@ -1261,6 +1294,18 @@ static ssize_t rawdev_write(struct device *dev, ///< ...@@ -1261,6 +1294,18 @@ static ssize_t rawdev_write(struct device *dev, ///<
// if (chunks[CHUNK_DATA_1].iov_len != 0) // if (chunks[CHUNK_DATA_1].iov_len != 0)
// chunks[CHUNK_DATA_1].iov_dma = dma_map_single(dev, chunks[CHUNK_DATA_1].iov_base, chunks[CHUNK_DATA_1].iov_len, DMA_TO_DEVICE); // chunks[CHUNK_DATA_1].iov_dma = dma_map_single(dev, chunks[CHUNK_DATA_1].iov_base, chunks[CHUNK_DATA_1].iov_len, DMA_TO_DEVICE);
/* performance calculations */
curr_mark.size = get_size_from(chunks, 0, 0, EXCLUDE_REM);
curr_mark.usec = get_rtc_usec();
curr_mark.sec = get_rtc_sec();
printk(KERN_DEBUG "current size: %u bytes\n", curr_mark.size);
printk(KERN_DEBUG "time diff: %u us\n", timediff(&prev_mark, &curr_mark));
printk(KERN_DEBUG "prev time stamp: sec = %u, usec = %u; curr time stamp: sec = %u, usec = %u\n", prev_mark.sec, prev_mark.usec, curr_mark.sec, curr_mark.usec);
if (prev_mark.sec != 0 && prev_mark.usec != 0)
total_datarate = prev_mark.size / timediff(&prev_mark, &curr_mark);
prev_mark = curr_mark;
/* end of performance calculations */
printk(KERN_DEBUG ">>> unaligned frame dump:\n"); printk(KERN_DEBUG ">>> unaligned frame dump:\n");
for (i = 0; i < MAX_DATA_CHUNKS; i++) { for (i = 0; i < MAX_DATA_CHUNKS; i++) {
printk(KERN_DEBUG ">>>\tslot: %i; len: %u\n", i, dpriv->data_chunks[i].iov_len); printk(KERN_DEBUG ">>>\tslot: %i; len: %u\n", i, dpriv->data_chunks[i].iov_len);
...@@ -1276,18 +1321,18 @@ static ssize_t rawdev_write(struct device *dev, ///< ...@@ -1276,18 +1321,18 @@ static ssize_t rawdev_write(struct device *dev, ///<
} }
process_cmd(dev, dpriv, port); process_cmd(dev, dpriv, port);
// while (dpriv->flags & PROC_CMD) { while (dpriv->flags & PROC_CMD) {
//#ifndef DEBUG_DONT_WRITE #ifndef DEBUG_DONT_WRITE
// while (dpriv->flags & IRQ_SIMPLE) { while (dpriv->flags & IRQ_SIMPLE) {
// printk_once(KERN_DEBUG ">>> waiting for interrupt\n"); printk_once(KERN_DEBUG ">>> waiting for interrupt\n");
// msleep_interruptible(1); msleep_interruptible(1);
// } }
//#endif #endif
// printk(KERN_DEBUG ">>> proceeding to next cmd chunk\n"); printk(KERN_DEBUG ">>> proceeding to next cmd chunk\n");
// sg_elems = process_cmd(dev, dpriv, port); sg_elems = process_cmd(dev, dpriv, port);
// if (sg_elems == 0) if (sg_elems == 0)
// finish_cmd(dev, dpriv); finish_cmd(dev, dpriv);
// } }
// if (chunks[CHUNK_DATA_0].iov_len != 0) // if (chunks[CHUNK_DATA_0].iov_len != 0)
// dma_unmap_single(dev, chunks[CHUNK_DATA_0].iov_dma, chunks[CHUNK_DATA_0].iov_len, DMA_TO_DEVICE); // dma_unmap_single(dev, chunks[CHUNK_DATA_0].iov_dma, chunks[CHUNK_DATA_0].iov_len, DMA_TO_DEVICE);
// if (chunks[CHUNK_DATA_1].iov_len != 0) // if (chunks[CHUNK_DATA_1].iov_len != 0)
...@@ -1503,6 +1548,7 @@ static struct attribute *root_dev_attrs[] = { ...@@ -1503,6 +1548,7 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_data_proc.attr, &dev_attr_data_proc.attr,
&dev_attr_exif_sz.attr, &dev_attr_exif_sz.attr,
&dev_attr_jpg_hdr_sz.attr, &dev_attr_jpg_hdr_sz.attr,
&dev_attr_datarate_mbs.attr,
NULL NULL
}; };
static const struct attribute_group dev_attr_root_group = { static const struct attribute_group dev_attr_root_group = {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/module.h>
#include <stddef.h> #include <stddef.h>
#include "x393_helpers.h" #include "x393_helpers.h"
...@@ -47,3 +48,32 @@ u32 get_rtc_usec(void) ...@@ -47,3 +48,32 @@ u32 get_rtc_usec(void)
} }
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(get_rtc_usec);
/**
* @brief Read RTC second counter.
* @return Current value of second counter or 0 in case read sequence was
* not successful.
*/
u32 get_rtc_sec(void)
{
x393_rtc_status_t stat;
x393_status_ctrl_t stat_ctrl;
x393_rtc_sec_t sec;
unsigned int i;
stat = x393_rtc_status();
stat_ctrl.d32 = 0;
stat_ctrl.mode = 1;
stat_ctrl.seq_num = stat.seq_num + 1;
set_x393_rtc_set_status(stat_ctrl);
for (i = 0; i < REPEAT_READ; i++) {
stat = x393_rtc_status();
if (stat.seq_num == stat_ctrl.seq_num) {
sec = x393_rtc_status_sec();
return sec.sec;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(get_rtc_sec);
...@@ -30,5 +30,6 @@ ...@@ -30,5 +30,6 @@
#define REPEAT_READ 10 #define REPEAT_READ 10
u32 get_rtc_usec(void); u32 get_rtc_usec(void);
u32 get_rtc_sec(void);
#endif /* _X393_HELPERS_H */ #endif /* _X393_HELPERS_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