// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "jfjoch_drv.h" #include #include 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; }