From d0c163ab63932a340dd20ade6984a5d6fd13d4ea Mon Sep 17 00:00:00 2001 From: Adam Wujek <adam.wujek@cern.ch> Date: Fri, 19 Feb 2016 11:35:59 +0100 Subject: [PATCH] kernel/wr_pstats: get rid of userv Apply zero bias at every read from FPGA. Signed-off-by: Adam Wujek <adam.wujek@cern.ch> --- kernel/wr_pstats/wr_pstats.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/kernel/wr_pstats/wr_pstats.c b/kernel/wr_pstats/wr_pstats.c index fe85890a3..5eb1dbf4e 100644 --- a/kernel/wr_pstats/wr_pstats.c +++ b/kernel/wr_pstats/wr_pstats.c @@ -116,7 +116,6 @@ struct cntrs_dev { /* there is no need to keep 64bits for zero values, * part which is read from FPGA is enough */ uint16_t zeros[PSTATS_MAX_NPORTS][PSTATS_MAX_NUM_OF_COUNTERS]; - uint64_t userv[PSTATS_MAX_NPORTS][PSTATS_MAX_NUM_OF_COUNTERS]; struct PSTATS_WB __iomem *regs; /* prevents from simultaneous access to cntrs array from tasklet and @@ -286,6 +285,10 @@ static int rd_cnt_word(int port, int adr) ptr = &(pstats_dev.cntrs[port][4 * adr + i]); *ptr &= PSTATS_MSB_MSK; *ptr |= hwcnt_to_sw(val[0], val[1], i); + /* apply zero bias, + * NOTE: since cntrs are monotonic, they're always bigger than + * zeros */ + *ptr -= pstats_dev.zeros[port][4 * adr + i]; spin_unlock(&pstats_dev.port_mutex[port]); } @@ -308,11 +311,16 @@ static void pstats_zero(int port) pstats_rd_cntrs(port); spin_lock(&pstats_dev.port_mutex[port]); for (i = 0; i < PSTATS_MAX_NUM_OF_COUNTERS; i++) { + /* since cntrs is monotonic it will never happen that zero will + * be bigger than cntrs */ + /* add zeros since it was substracted before in + * pstats_rd_cntrs (rd_cnt_word) */ + pstats_dev.cntrs[port][i] += pstats_dev.zeros[port][i]; + /* clear 48 MSBits */ + pstats_dev.cntrs[port][i] &= PSTATS_LSB_MSK; /* Copy 16 LSBits to zero */ pstats_dev.zeros[port][i] = (uint16_t) pstats_dev.cntrs[port][i]; - /* clear 48 MSBits */ - pstats_dev.cntrs[port][i] &= PSTATS_LSB_MSK; } spin_unlock(&pstats_dev.port_mutex[port]); } @@ -340,8 +348,8 @@ static int pstats_desc_handler(ctl_table *ctl, int write, void *buffer, static int pstats_handler(ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) { - int i, port; - struct cntrs_dev *d = &pstats_dev; + int port; + int ret; port = (int)ctl->extra1; @@ -357,18 +365,23 @@ static int pstats_handler(ctl_table *ctl, int write, void *buffer, } if (port < pstats_nports) { + /* read counters including correction of zeros offset */ pstats_rd_cntrs(port); - for (i = 0; i < firmware_counters; i++) - d->userv[port][i] = d->cntrs[port][i] - d->zeros[port][i]; } else { /* stuff for info file, read at module load time */ pstats_info[PINFO_VER] = firmware_version; pstats_info[PINFO_CNTPW] = firmware_cpw; pstats_info[PINFO_CNTPP] = firmware_counters; } + /* It might happen that irq comes between reading MSB 32 bits and + * LSB 32 bits of particualr counter. + * In that case counter's value would be lower than previous one */ + spin_lock(&pstats_dev.port_mutex[port]); /* each value will be split into two unsigned longs, * each counter has to be assembled in software reading pstats */ - return proc_dointvec(ctl, 0, buffer, lenp, ppos); + ret = proc_dointvec(ctl, 0, buffer, lenp, ppos); + spin_unlock(&pstats_dev.port_mutex[port]); + return ret; } /* one per port, then info and description, and terminator, filled at init time */ @@ -470,7 +483,7 @@ static int __init pstats_init(void) for (i = 0; i < pstats_nports; ++i) { pstats_ctl_table[i].procname = portnames[i]; - pstats_ctl_table[i].data = &pstats_dev.userv[i]; + pstats_ctl_table[i].data = &pstats_dev.cntrs[i]; /* each value will be split into two unsigned longs, * each counter has to be assembled in software reading pstats */ -- GitLab