Files
Jungfraujoch/fpga/pcie_driver/jfjoch_miscdev.c
2024-11-22 21:25:20 +01:00

62 lines
2.1 KiB
C

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "jfjoch_drv.h"
#include <linux/module.h>
#include <linux/spinlock.h>
static int device_index = 0;
int jfjoch_register_misc_dev(struct pci_dev *pdev) {
int err;
struct jfjoch_drvdata *drvdata = pci_get_drvdata(pdev);
drvdata->file_write_open_count = 0;
spin_lock_init(&drvdata->file_write_open_count_spinlock);
snprintf( drvdata->name, 255, "jfjoch%d", device_index++);
drvdata->miscdev.parent = &pdev->dev;
drvdata->miscdev.mode = 0664;
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
drvdata->miscdev.fops = &jfjoch_cdev_fileops;
drvdata->miscdev.name = drvdata->name;
err = misc_register(&drvdata->miscdev);
if (err)
pr_notice("Misc device registration failed\n");
return err;
}
void jfjoch_unregister_misc_dev(struct pci_dev *pdev) {
struct jfjoch_drvdata *drvdata = pci_get_drvdata(pdev);
misc_deregister(&drvdata->miscdev);
}
int jfjoch_cdev_open(struct inode *inode, struct file *file) {
struct jfjoch_drvdata *drvdata = container_of(file->private_data, struct jfjoch_drvdata, miscdev);
bool ok = true;
if (file->f_mode & FMODE_WRITE) {
unsigned long flags;
spin_lock_irqsave(&drvdata->file_write_open_count_spinlock, flags);
ok = (drvdata->file_write_open_count == 0);
drvdata->file_write_open_count = 1;
spin_unlock_irqrestore(&drvdata->file_write_open_count_spinlock, flags);
}
if (!ok)
return -EBUSY;
return 0;
}
int jfjoch_cdev_release(struct inode *inode, struct file *file) {
struct jfjoch_drvdata *drvdata = container_of(file->private_data, struct jfjoch_drvdata, miscdev);
if (file->f_mode & FMODE_WRITE) {
unsigned long flags;
jfjoch_cancel(drvdata);
spin_lock_irqsave(&drvdata->file_write_open_count_spinlock, flags);
drvdata->file_write_open_count = 0;
spin_unlock_irqrestore(&drvdata->file_write_open_count_spinlock, flags);
}
return 0;
}