Commit b8f7b8f0 authored by Jens Korinth's avatar Jens Korinth
Browse files

WIP: re-activate performance counter files

* continued refactoring: some file renames in device/
* changed deactivate compile flag for performance counters to NPERFC
* re-inserted per-device perfc file with default output
* changed performance counter names and implemented counting
* implemented add function for counters to increase by more than 1
* added filename pattern to tlkm_device_ioctl_cmds.h
parent a3f80c8c
......@@ -8,7 +8,25 @@ CROSS_COMPILE ?= arm-linux-gnueabihf-
endif
obj-m += tlkm.o
tlkm-objs := tlkm_module.o tlkm/tlkm_logging.o tlkm/tlkm_bus.o tlkm/tlkm.o tlkm/tlkm_ioctl.o tlkm/tlkm_device.o device/tlkm_perfc.o device/tlkm_perfc_miscdev.o device/tlkm_control.o device/tlkm_control_fops.o device/tlkm_device_ioctl.o device/tlkm_device_mmap.o zynq/zynq_enumerate.o zynq/zynq_device.o zynq/zynq_ioctl.o zynq/zynq_dmamgmt.o zynq/zynq_irq.o zynq/zynq_mmap.o
tlkm-objs := \
tlkm_module.o \
tlkm/tlkm_logging.o \
tlkm/tlkm_bus.o \
tlkm/tlkm.o \
tlkm/tlkm_ioctl.o \
tlkm/tlkm_device.o \
device/tlkm_perfc.o \
device/tlkm_perfc_miscdev.o \
device/tlkm_control.o \
device/tlkm_device_rw.o \
device/tlkm_device_ioctl.o \
device/tlkm_device_mmap.o \
zynq/zynq_enumerate.o \
zynq/zynq_device.o \
zynq/zynq_ioctl.o \
zynq/zynq_dmamgmt.o \
zynq/zynq_irq.o \
zynq/zynq_mmap.o
CPPFLAGS+=-I$(TAPASCO_HOME)/tlkm -I$(TAPASCO_HOME)/tlkm/device -I$(TAPASCO_HOME)/tlkm/tlkm -I$(TAPASCO_HOME)/tlkm/user -I$(TAPASCO_HOME)/platform/include
......
......@@ -38,7 +38,7 @@ Directory Structure <a name="dirs"/>
```
/ <- should only contain the top-level module definitions
/tlkm <- contains code for top-level device management
/common <- contains re-usable shared code and definitions
/device <- contains code for handling a device instance
/user <- contains headers to be included in user-space progs
/<PLATFORM> <- contains platform specific code and enumerators
```
......@@ -48,7 +48,7 @@ Overview <a name="overview"/>
The base module only initializes `tlkm_bus`. `tlkm_bus` calls a number of device
enumerators from the `/<PLATFORM>` subdirectory to get a list with names and
device ids (see `common/tlkm_devices.h` for the `struct` def). The init and exit
device ids (see `device/tlkm_devices.h` for the `struct` def). The init and exit
function pointers link to the platform-specific code for device initialization
and tear-down. They will be used when user space creates the corresponding
device to setup the device-specific OS interfaces.
......@@ -113,7 +113,7 @@ additionally have a `tlkm_<DEV_ID>_perfc` file giving access to device internal
performance counters, e.g., the total number of completed jobs, or the number of
completed jobs per slot.
**Important:** Performance counters are defined in `/common/tlkm_perfc.h` and
**Important:** Performance counters are defined in `/device/tlkm_perfc.h` and
should always be the same for all devices. Defining a new performance counter
there automatically defines `tlkm_perfc_<name>_inc` and `tlkm_perfc_<name>_get`
functions, which can be used by your driver to access the counters. If you need
......
......@@ -3,23 +3,23 @@
#include <linux/fs.h>
#include "tlkm_logging.h"
#include "tlkm_control.h"
#include "tlkm_control_fops.h"
#include "tlkm_perfc.h"
#include "tlkm_device_rw.h"
#include "tlkm_device_ioctl.h"
#include "tlkm_device_mmap.h"
static const struct file_operations _tlkm_control_fops = {
.unlocked_ioctl = tlkm_device_ioctl,
.mmap = tlkm_device_mmap,
.read = tlkm_control_fops_read,
.write = tlkm_control_fops_write,
.read = tlkm_device_read,
.write = tlkm_device_write,
};
static int init_miscdev(struct tlkm_control *pctl)
{
char fn[16];
snprintf(fn, 16, "tlkm_%03u", pctl->dev_id);
LOG(TLKM_LF_CONTROL, "creating miscdevice %s for device #%03u", fn, pctl->dev_id);
DEVLOG(pctl->dev_id, TLKM_LF_CONTROL, "creating miscdevice %s", fn);
pctl->miscdev.minor = MISC_DYNAMIC_MINOR;
pctl->miscdev.name = kstrdup(fn, GFP_KERNEL);
pctl->miscdev.fops = &_tlkm_control_fops;
......@@ -31,29 +31,29 @@ static void exit_miscdev(struct tlkm_control *pctl)
misc_deregister(&pctl->miscdev);
kfree(pctl->miscdev.name);
pctl->miscdev.name = NULL;
LOG(TLKM_LF_CONTROL, "destroyed miscdevice for device #%03u", pctl->dev_id);
DEVLOG(pctl->dev_id, TLKM_LF_CONTROL, "destroyed miscdevice");
}
ssize_t tlkm_control_signal_slot_interrupt(struct tlkm_control *pctl, const u32 s_id)
{
mutex_lock(&pctl->out_mutex);
while (pctl->outstanding > TLKM_CONTROL_BUFFER_SZ - 2) {
WRN("buffer thrashing, throttling write ...");
DEVWRN(pctl->dev_id, "buffer thrashing, throttling write ...");
mutex_unlock(&pctl->out_mutex);
wait_event_interruptible(pctl->write_q, pctl->outstanding <= (TLKM_CONTROL_BUFFER_SZ / 2));
if (signal_pending(current)) return -ERESTARTSYS;
mutex_lock(&pctl->out_mutex);
}
mutex_unlock(&pctl->out_mutex);
LOG(TLKM_LF_CONTROL, "device #%03u: signaling slot #%u", pctl->dev_id, s_id);
DEVLOG(pctl->dev_id, TLKM_LF_CONTROL, "signaling slot #%u", s_id);
mutex_lock(&pctl->out_mutex);
pctl->out_slots[pctl->out_w_idx] = s_id;
pctl->out_w_idx = (pctl->out_w_idx + 1) % TLKM_CONTROL_BUFFER_SZ;
++pctl->outstanding;
tlkm_perfc_control_signaled_inc(pctl->dev_id);
tlkm_perfc_signals_signaled_inc(pctl->dev_id);
#ifndef NDEBUG
if (pctl->outstanding >= TLKM_CONTROL_BUFFER_SZ)
WRN("buffer size exceeded! expect missing data!");
DEVWRN(pctl->dev_id, "buffer size exceeded! expect missing data!");
#endif
mutex_unlock(&pctl->out_mutex);
wake_up_interruptible(&pctl->read_q);
......@@ -65,7 +65,7 @@ int tlkm_control_init(dev_id_t dev_id, struct tlkm_control **ppctl)
int ret = 0;
struct tlkm_control *p = (struct tlkm_control *)kzalloc(sizeof(*p), GFP_KERNEL);
if (! p) {
ERR("could not allocate struct tlkm_control");
DEVERR(dev_id, "could not allocate struct tlkm_control");
return -ENOMEM;
}
p->dev_id = dev_id;
......@@ -76,11 +76,11 @@ int tlkm_control_init(dev_id_t dev_id, struct tlkm_control **ppctl)
p->outstanding = 0;
mutex_init(&p->out_mutex);
if ((ret = init_miscdev(p))) {
ERR("could not initialize control for device #%03u: %d", dev_id, ret);
DEVERR(dev_id, "could not initialize control: %d", ret);
goto err_miscdev;
}
*ppctl = p;
LOG(TLKM_LF_CONTROL, "initialized control for device #%03u", dev_id);
DEVLOG(dev_id, TLKM_LF_CONTROL, "initialized control");
return 0;
err_miscdev:
......@@ -92,7 +92,7 @@ void tlkm_control_exit(struct tlkm_control *pctl)
{
if (pctl) {
exit_miscdev(pctl);
LOG(TLKM_LF_CONTROL, "destroyed control for device #%03u", pctl->dev_id);
DEVLOG(pctl->dev_id, TLKM_LF_CONTROL, "destroyed control");
kfree(pctl);
}
}
#ifndef TLKM_CONTROL_FOPS_H__
#define TLKM_CONTROL_FOPS_H__
#include <linux/fs.h>
ssize_t tlkm_control_fops_read(struct file *fp, char __user *d, size_t sz, loff_t *off);
ssize_t tlkm_control_fops_write(struct file *fp, const char __user *d, size_t sz, loff_t *off);
long tlkm_control_fops_ioctl(struct file *fp, unsigned int ioctl, unsigned long data);
#endif /* TLKM_CONTROL_FOPS_H__ */
......@@ -55,6 +55,7 @@ long tlkm_device_ioctl_info(struct file *fp, unsigned int ioctl,
long tlkm_device_ioctl(struct file *fp, unsigned int ioctl, unsigned long data)
{
tlkm_perfc_control_ioctls_inc(device_from_file(fp)->dev_id);
if (ioctl == TLKM_DEV_IOCTL_INFO) {
return tlkm_device_ioctl_info(fp, ioctl, (struct tlkm_device_info __user *)data);
} else {
......
#include <linux/uaccess.h>
#include "tlkm_control_fops.h"
#include "tlkm_device_rw.h"
#include "tlkm_control.h"
#include "tlkm_perfc.h"
#include "tlkm_logging.h"
......@@ -10,7 +10,7 @@ inline static struct tlkm_control *control_from_file(struct file *fp)
return container_of(m, struct tlkm_control, miscdev);
}
ssize_t tlkm_control_fops_read(struct file *fp, char __user *usr, size_t sz, loff_t *off)
ssize_t tlkm_device_read(struct file *fp, char __user *usr, size_t sz, loff_t *off)
{
ssize_t out = 0;
u32 out_val = 0;
......@@ -26,7 +26,7 @@ ssize_t tlkm_control_fops_read(struct file *fp, char __user *usr, size_t sz, lof
out_val = pctl->out_slots[pctl->out_r_idx];
pctl->out_r_idx = (pctl->out_r_idx + 1) % TLKM_CONTROL_BUFFER_SZ;
--pctl->outstanding;
tlkm_perfc_control_read_inc(pctl->dev_id);
tlkm_perfc_signals_read_inc(pctl->dev_id);
}
mutex_unlock(&pctl->out_mutex);
if (! out) {
......@@ -43,7 +43,7 @@ ssize_t tlkm_control_fops_read(struct file *fp, char __user *usr, size_t sz, lof
return sizeof(out_val);
}
ssize_t tlkm_control_fops_write(struct file *fp, const char __user *usr, size_t sz, loff_t *off)
ssize_t tlkm_device_write(struct file *fp, const char __user *usr, size_t sz, loff_t *off)
{
u32 in_val = 0;
ssize_t in;
......@@ -53,7 +53,7 @@ ssize_t tlkm_control_fops_write(struct file *fp, const char __user *usr, size_t
return -EFAULT;
}
in = copy_from_user(&in_val, usr, sizeof(in_val));
tlkm_perfc_control_written_inc(pctl->dev_id);
tlkm_perfc_signals_written_inc(pctl->dev_id);
DEVLOG(pctl->dev_id, TLKM_LF_CONTROL, "received job %u as write", in_val);
if (in) return -EFAULT;
return tlkm_control_signal_slot_interrupt(pctl, in_val);
......
#ifndef TLKM_DEVICE_RW_H__
#define TLKM_DEVICE_RW_H__
#include <linux/fs.h>
ssize_t tlkm_device_read(struct file *fp, char __user *d, size_t sz, loff_t *off);
ssize_t tlkm_device_write(struct file *fp, const char __user *d, size_t sz, loff_t *off);
#endif /* TLKM_DEVICE_RW_H__ */
......@@ -26,7 +26,7 @@
#include "tlkm_ioctl_cmds.h"
#include "tlkm_perfc.h"
#ifndef NDEBUG
#ifndef NPERFC
static
struct tlkm_perfc_t {
......@@ -41,6 +41,11 @@ void tlkm_perfc_ ## name ## _inc(dev_id_t dev_id) \
atomic_inc(&tlkm_perfc.pc_ ## name[dev_id]); \
} \
\
void tlkm_perfc_ ## name ## _add(dev_id_t dev_id, int const v) \
{ \
atomic_add(v, &tlkm_perfc.pc_ ## name[dev_id]); \
} \
\
int tlkm_perfc_ ## name ## _get(dev_id_t dev_id) \
{ \
return atomic_read(&tlkm_perfc.pc_ ## name[dev_id]); \
......
......@@ -32,31 +32,34 @@
#endif
#define TLKM_PERFC_COUNTERS \
_PC(control_read) \
_PC(control_written) \
_PC(control_signaled) \
_PC(total_mem) \
_PC(dma_transfers) \
_PC(dma_bytes)
_PC(signals_read) \
_PC(signals_written) \
_PC(signals_signaled) \
_PC(control_ioctls) \
_PC(total_alloced_mem) \
_PC(total_freed_mem) \
_PC(total_usr2dev_transfers) \
_PC(total_dev2usr_transfers) \
_PC(total_ctl_writes) \
_PC(total_ctl_reads)
#ifndef NDEBUG
#include <linux/types.h>
#ifndef NPERFC
#include <linux/types.h>
#define _PC(name) \
void tlkm_perfc_ ## name ## _inc(dev_id_t dev_id); \
int tlkm_perfc_ ## name ## _get(dev_id_t dev_id);
#define _PC(name) \
void tlkm_perfc_ ## name ## _inc(dev_id_t dev_id); \
void tlkm_perfc_ ## name ## _add(dev_id_t dev_id, int const v); \
int tlkm_perfc_ ## name ## _get(dev_id_t dev_id);
TLKM_PERFC_COUNTERS
#undef _PC
#else /* NDEBUG */
#define _PC(name) \
inline static void tlkm_perfc_ ## name ## _inc(dev_id_t dev_id) {} \
inline static int tlkm_perfc_ ## name ## _get(dev_id_t dev_id) { return 0; } \
TLKM_PERFC_COUNTERS
#undef _PC
TLKM_PERFC_COUNTERS
#undef _PC
#else /* NPERFC */
#define _PC(name) \
inline static void tlkm_perfc_ ## name ## _inc(dev_id_t dev_id) {} \
inline static void tlkm_perfc_ ## name ## _add(dev_id_t dev_id, int const v) {} \
inline static int tlkm_perfc_ ## name ## _get(dev_id_t dev_id) { return 0; } \
#endif /* NDEBUG */
TLKM_PERFC_COUNTERS
#undef _PC
#endif /* NPERFC */
#endif /* TLKM_PERFC_H__ */
......@@ -28,8 +28,9 @@
#include "tlkm_perfc.h"
#include "tlkm_perfc_miscdev.h"
#include "tlkm_logging.h"
#include "tlkm_device_ioctl_cmds.h"
#ifndef NDEBUG
#ifndef NPERFC
#define TLKM_PERFC_MISCDEV_BUFSZ 512
inline static
......@@ -76,16 +77,16 @@ int tlkm_perfc_miscdev_init(struct tlkm_device_inst *dev)
{
int ret = 0;
char fn[256];
snprintf(fn, 256, "/dev/tlkm%03u_perfc", dev->dev_id);
LOG(TLKM_LF_PERFC, "setting up performance counter file %s ...", fn);
snprintf(fn, 256, TLKM_DEV_PERFC_FN, dev->dev_id);
DEVLOG(dev->dev_id, TLKM_LF_PERFC, "setting up performance counter file %s ...", fn);
dev->perfc_dev.minor = MISC_DYNAMIC_MINOR;
dev->perfc_dev.name = kstrdup(fn, GFP_KERNEL);
dev->perfc_dev.fops = &tlkm_perfc_miscdev_fops;
if ((ret = misc_register(&dev->perfc_dev))) {
ERR("could not setup %s: %d", fn, ret);
DEVERR(dev->dev_id, "could not setup %s: %d", fn, ret);
return ret;
}
LOG(TLKM_LF_PERFC, "%s is set up", fn);
DEVLOG(dev->dev_id, TLKM_LF_PERFC, "%s is set up", fn);
return 0;
}
......@@ -93,6 +94,6 @@ void tlkm_perfc_miscdev_exit(struct tlkm_device_inst *dev)
{
misc_deregister(&dev->perfc_dev);
kfree(dev->perfc_dev.name);
LOG(TLKM_LF_PERFC, "removed performance counter miscdev");
DEVLOG(dev->dev_id, TLKM_LF_PERFC, "removed performance counter miscdev");
}
#endif /* NDEBUG */
#endif /* NPERFC */
......@@ -3,6 +3,7 @@
#include "tlkm_logging.h"
#include "tlkm_device.h"
#include "tlkm_control.h"
#include "tlkm_perfc_miscdev.h"
static
int create_device_instance(struct tlkm_device *pdev, tlkm_access_t access)
......@@ -22,8 +23,18 @@ int create_device_instance(struct tlkm_device *pdev, tlkm_access_t access)
ERR("could not setup control for device #%03u: %d", pdev->dev_id, ret);
goto err_control;
}
if ((ret = tlkm_perfc_miscdev_init(pdev->inst))) {
ERR("could not setup performance counter device file for device #%03u: %d",
pdev->dev_id, ret);
goto err_nperfc;
}
return pdev->init(pdev->inst);
tlkm_perfc_miscdev_exit(pdev->inst);
err_nperfc:
tlkm_control_exit(pdev->inst->ctrl);
err_control:
kfree(pdev->inst);
pdev->inst = NULL;
......@@ -35,6 +46,7 @@ void destroy_device_instance(struct tlkm_device *pdev)
{
if (pdev->inst) {
pdev->exit(pdev->inst);
tlkm_perfc_miscdev_exit(pdev->inst);
tlkm_control_exit(pdev->inst->ctrl);
kfree(pdev->inst);
pdev->inst = NULL;
......
......@@ -49,6 +49,7 @@ struct tlkm_bulk_cmd {
};
#define TLKM_DEV_IOCTL_FN "tlkm_%03u"
#define TLKM_DEV_PERFC_FN "tlkm_perfc_%03u"
#ifdef _TLKM_DEV_IOCTL
#undef _TLKM_DEV_IOCTL
......
......@@ -85,22 +85,21 @@ int zynq_device_init(struct tlkm_device_inst *inst)
return -EACCES;
}
#endif /* NDEBUG */
LOG(TLKM_LF_DEVICE, "initializing zynq device #%03u", inst->dev_id);
DEVLOG(inst->dev_id, TLKM_LF_DEVICE, "initializing zynq device");
inst->private_data = (void *)&_zynq_dev;
_zynq_dev.dev_id = inst->dev_id;
if ((ret = init_iomapping())) {
ERR("could not initialize io-mapping: %d", ret);
DEVERR(inst->dev_id, "could not initialize I/O-mapping: %d", ret);
goto err_iomapping;
}
if ((ret = zynq_irq_init(&_zynq_dev, inst->ctrl))) {
ERR("could not initialize interrupts: %d", ret);
DEVERR(inst->dev_id, "could not initialize interrupts: %d", ret);
goto err_irq;
}
LOG(TLKM_LF_DEVICE, "zynq device #%03u successfully initialized",
_zynq_dev.dev_id);
DEVLOG(inst->dev_id, TLKM_LF_DEVICE, "zynq successfully initialized");
return 0;
err_irq:
......@@ -120,5 +119,5 @@ void zynq_device_exit(struct tlkm_device_inst *inst)
zynq_irq_exit(&_zynq_dev);
exit_iomapping();
inst->private_data = NULL;
LOG(TLKM_LF_DEVICE, "zynq device #%03u exited", _zynq_dev.dev_id);
DEVLOG(_zynq_dev.dev_id, TLKM_LF_DEVICE, "zynq device exited");
}
......@@ -60,6 +60,7 @@ long zynq_ioctl_alloc(struct tlkm_device_inst *inst, struct tlkm_mm_cmd *cmd)
DEVWRN(inst->dev_id, "allocation failed");
return -ENOMEM;
}
tlkm_perfc_total_alloced_mem_add(inst->dev_id, cmd->sz);
return 0;
}
......@@ -70,6 +71,7 @@ long zynq_ioctl_free(struct tlkm_device_inst *inst, struct tlkm_mm_cmd *cmd)
if (cmd->dev_addr >= 0) {
zynq_dmamgmt_dealloc(cmd->dev_addr);
cmd->dev_addr = -1;
tlkm_perfc_total_freed_mem_add(inst->dev_id, cmd->sz);
}
return 0;
}
......@@ -102,6 +104,7 @@ long zynq_ioctl_copyto(struct tlkm_device_inst *inst, struct tlkm_copy_cmd *cmd)
return -EACCES;
}
DEVLOG(inst->dev_id, TLKM_LF_IOCTL, "copyto finished successfully");
tlkm_perfc_total_usr2dev_transfers_add(inst->dev_id, cmd->length);
return 0;
}
......@@ -121,6 +124,7 @@ long zynq_ioctl_copyfrom(struct tlkm_device_inst *inst, struct tlkm_copy_cmd *cm
return -EACCES;
}
DEVLOG(inst->dev_id, TLKM_LF_IOCTL, "copyfrom finished successfully");
tlkm_perfc_total_dev2usr_transfers_add(inst->dev_id, cmd->length);
return 0;
}
......@@ -184,6 +188,7 @@ long zynq_ioctl_read(struct tlkm_device_inst *inst, struct tlkm_copy_cmd *cmd)
ret = -EAGAIN;
}
kfree(buf);
tlkm_perfc_total_ctl_reads_add(inst->dev_id, cmd->length);
return ret;
}
......@@ -215,6 +220,7 @@ long zynq_ioctl_write(struct tlkm_device_inst *inst, struct tlkm_copy_cmd *cmd)
memcpy_toio(ptr, buf, cmd->length);
err:
kfree(buf);
tlkm_perfc_total_ctl_writes_add(inst->dev_id, cmd->length);
return ret;
}
......
Supports Markdown
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