PCIe driver: Added sysfs bindings

This commit is contained in:
2023-10-24 09:25:43 +02:00
parent 6d74732bf5
commit 79d7254555
6 changed files with 195 additions and 3 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
# but it helps in code completion in CLion IDE
ADD_LIBRARY(jfjoch_kernel_module STATIC
jfjoch_ioctl.h jfjoch_drv.c jfjoch_drv.h jfjoch_ioctl.h jfjoch_pcie_setup.c jfjoch_memory.c jfjoch_ioctl.c jfjoch_function.c jfjoch_miscdev.c)
jfjoch_ioctl.h jfjoch_drv.c jfjoch_drv.h jfjoch_ioctl.h jfjoch_pcie_setup.c jfjoch_memory.c jfjoch_ioctl.c jfjoch_function.c jfjoch_miscdev.c
jfjoch_sysfs.c)
EXECUTE_PROCESS(COMMAND uname -r
OUTPUT_VARIABLE KERNEL_RELEASE
+1 -1
View File
@@ -1,7 +1,7 @@
obj-m += jfjoch.o
cflags-m=-std=c99
jfjoch-y := jfjoch_drv.o jfjoch_ioctl.o jfjoch_memory.o jfjoch_pcie_setup.o jfjoch_function.o jfjoch_miscdev.o
jfjoch-y := jfjoch_drv.o jfjoch_ioctl.o jfjoch_memory.o jfjoch_pcie_setup.o jfjoch_function.o jfjoch_miscdev.o jfjoch_sysfs.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(CURDIR) modules
+8
View File
@@ -83,9 +83,16 @@ static int jfjoch_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
jfjoch_setup_cms(drvdata);
jfjoch_setup_network(drvdata);
err = jfjoch_register_sysfs(drvdata);
if (err)
goto unregister_sysfs;
dev_info(drvdata->miscdev.this_device, "Jungfraujoch FPGA loaded with FW build: %x", drvdata->git_sha1);
return 0;
unregister_sysfs:
jfjoch_unregister_sysfs(drvdata);
deregister_misc:
misc_deregister(&drvdata->miscdev);
@@ -119,6 +126,7 @@ static void jfjoch_pci_remove(struct pci_dev *pdev) {
pci_clear_master(pdev);
jfjoch_unregister_sysfs(drvdata);
jfjoch_unregister_misc_dev(pdev);
jfjoch_free_phys_continous_buf(pdev);
pci_iounmap(pdev, drvdata->bar0);
+3
View File
@@ -142,6 +142,9 @@ void jfjoch_reset(struct jfjoch_drvdata *drvdata);
void jfjoch_write_register(struct jfjoch_drvdata *drvdata, uint32_t addr, uint32_t val);
uint32_t jfjoch_read_register(struct jfjoch_drvdata *drvdata, uint32_t addr);
int jfjoch_register_sysfs(struct jfjoch_drvdata *drvdata);
void jfjoch_unregister_sysfs(struct jfjoch_drvdata *drvdata);
static const struct file_operations jfjoch_cdev_fileops = {
.mmap = jfjoch_cdev_mmap,
.unlocked_ioctl = jfjoch_cdev_ioctl,
+1 -1
View File
@@ -10,7 +10,7 @@ int jfjoch_register_misc_dev(struct pci_dev *pdev) {
struct jfjoch_drvdata *drvdata = pci_get_drvdata(pdev);
snprintf( drvdata->name, 255, "jfjoch%d", device_index++);
drvdata->miscdev.parent = &pdev->dev;
drvdata->miscdev.mode = 0660;
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
drvdata->miscdev.fops = &jfjoch_cdev_fileops;
+180
View File
@@ -0,0 +1,180 @@
// Copyright (2019-2023) Paul Scherrer Institute
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/pci.h>
#include "jfjoch_drv.h"
static ssize_t hbm0_temp_degC_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
unsigned int val = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_HBM_TEMP1_INS_REG);
return scnprintf(buf, PAGE_SIZE, "%d", val);
}
static ssize_t hbm1_temp_degC_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
unsigned int val = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_HBM_TEMP2_INS_REG);
return scnprintf(buf, PAGE_SIZE, "%d", val);
}
static ssize_t fpga_temp_degC_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
unsigned int val = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_FPGA_TEMP_INS_REG);
return scnprintf(buf, PAGE_SIZE, "%d", val);
}
static ssize_t fpga_power_mW_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
u32 fpga_pcie_3p3V_I_mA = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_3V3PEX_I_IN_INS_REG);
u32 fpga_pcie_12V_I_mA = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_12VPEX_I_IN_INS_REG);
u32 fpga_pcie_3p3V_V_mV = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_3V3_PEX_INS_REG);
u32 fpga_pcie_12V_V_mV = ioread32(drvdata->bar0 + CMS_OFFSET + ADDR_CMS_12V_PEX_INS_REG);
u32 power_mW = (fpga_pcie_3p3V_I_mA * fpga_pcie_3p3V_V_mV + fpga_pcie_12V_I_mA * fpga_pcie_12V_V_mV) / 1000;
return scnprintf(buf, PAGE_SIZE, "%d", power_mW);
}
static ssize_t status_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
unsigned int val = ioread32(drvdata->bar0 + ACTION_CONFIG_OFFSET + ADDR_CTRL_REGISTER);
return scnprintf(buf, PAGE_SIZE, "%d", val);
}
static ssize_t eth_aligned_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
// Need to ask twice to get recent answer
ioread32(drvdata->bar0 + CMAC_OFFSET + 0x0204);
unsigned int val = ioread32(drvdata->bar0 + CMAC_OFFSET + 0x0204) & 0x2;
return scnprintf(buf, PAGE_SIZE, "%d", val);
}
static ssize_t git_sha1_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
return scnprintf(buf, PAGE_SIZE, "%x", drvdata->git_sha1);
}
static ssize_t max_modules_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
return scnprintf(buf, PAGE_SIZE, "%x", drvdata->max_modules);
}
static ssize_t stalls_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
u64 val0 = ioread32(drvdata->bar0 + ACTION_CONFIG_OFFSET + ADDR_STALLS_HBM_LO);
u64 val1 = ioread32(drvdata->bar0 + ACTION_CONFIG_OFFSET + ADDR_STALLS_HBM_HI);
u64 val = (val1 << 32) | val0;
return scnprintf(buf, PAGE_SIZE, "%lld", val);
}
static ssize_t ipv4_addr_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
u32 val = ioread32((drvdata->bar0) + ACTION_CONFIG_OFFSET + ADDR_IPV4_ADDR);
return scnprintf(buf, PAGE_SIZE, "0x%x", val);
}
static ssize_t mac_addr_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct miscdevice* miscdev = dev_get_drvdata(dev);
struct jfjoch_drvdata* drvdata = container_of(miscdev, struct jfjoch_drvdata, miscdev);
u64 val0 = ioread32(drvdata->bar0 + ACTION_CONFIG_OFFSET + ADDR_MAC_ADDR_LO);
u64 val1 = ioread32(drvdata->bar0 + ACTION_CONFIG_OFFSET + ADDR_MAC_ADDR_HI);
u64 val = (val1 << 32) | val0;
return scnprintf(buf, PAGE_SIZE, "0x%llx", val);
}
static ssize_t nbuffers_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
return scnprintf(buf, 25, "%d", nbuffer);
}
static ssize_t release_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
return scnprintf(buf, 25, "%d", RELEASE_LEVEL);
}
static struct device_attribute device_attrs[] = {
__ATTR_RO(hbm0_temp_degC),
__ATTR_RO(hbm1_temp_degC),
__ATTR_RO(fpga_temp_degC),
__ATTR_RO(fpga_power_mW),
__ATTR_RO(nbuffers),
__ATTR_RO(stalls),
__ATTR_RO(status),
__ATTR_RO(git_sha1),
__ATTR_RO(release),
__ATTR_RO(max_modules),
__ATTR_RO(eth_aligned),
__ATTR_RO(mac_addr),
__ATTR_RO(ipv4_addr)
};
int jfjoch_register_sysfs(struct jfjoch_drvdata *drvdata) {
if (!drvdata)
return -EINVAL;
int i, err;
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
err = device_create_file(drvdata->miscdev.this_device, &device_attrs[i]);
if (err) {
dev_err(drvdata->miscdev.this_device, "Failed to create sysfs file");
break;
}
}
if (err) {
while (--i >= 0)
device_remove_file(drvdata->miscdev.this_device,
&device_attrs[i]);
}
return err;
}
void jfjoch_unregister_sysfs(struct jfjoch_drvdata *drvdata) {
int i;
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
device_remove_file(drvdata->miscdev.this_device, &device_attrs[i]);
}