lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260206191136.2609767-4-slava@dubeyko.com>
Date: Fri,  6 Feb 2026 11:11:35 -0800
From: Viacheslav Dubeyko <slava@...eyko.com>
To: linux-fsdevel@...r.kernel.org,
	linux-mm@...ck.org,
	bpf@...r.kernel.org
Cc: Slava.Dubeyko@....com,
	slava@...eyko.com,
	linux-kernel@...r.kernel.org
Subject: [RFC PATCH v1 3/4] ml-lib: Implement simple testing character device driver

Implement simple testing character device driver

Signed-off-by: Viacheslav Dubeyko <slava@...eyko.com>
---
 lib/ml-lib/test_driver/Kconfig           |  22 +
 lib/ml-lib/test_driver/Makefile          |   5 +
 lib/ml-lib/test_driver/README.md         | 233 ++++++++++
 lib/ml-lib/test_driver/ml_lib_char_dev.c | 530 +++++++++++++++++++++++
 4 files changed, 790 insertions(+)
 create mode 100644 lib/ml-lib/test_driver/Kconfig
 create mode 100644 lib/ml-lib/test_driver/Makefile
 create mode 100644 lib/ml-lib/test_driver/README.md
 create mode 100644 lib/ml-lib/test_driver/ml_lib_char_dev.c

diff --git a/lib/ml-lib/test_driver/Kconfig b/lib/ml-lib/test_driver/Kconfig
new file mode 100644
index 000000000000..183fc1de57a8
--- /dev/null
+++ b/lib/ml-lib/test_driver/Kconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ML_LIB_TEST_DRIVER
+	tristate "ML library testing character device driver"
+	depends on ML_LIB
+	default n
+	help
+	  This is a ML library testing character device driver for
+	  testing generic ML library functionality. It provides:
+
+	  - Basic read/write operations
+	  - IOCTL interface for device control
+	  - Sysfs attributes for runtime information
+	  - Procfs entry for debugging
+
+	  The driver creates a /dev/mllibdev device node that can be
+	  used to read and write data to a kernel buffer.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mllibdev.
diff --git a/lib/ml-lib/test_driver/Makefile b/lib/ml-lib/test_driver/Makefile
new file mode 100644
index 000000000000..6444bcf8985b
--- /dev/null
+++ b/lib/ml-lib/test_driver/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_ML_LIB_TEST_DRIVER) += ml_lib_test_dev.o
+
+ml_lib_test_dev-y := ml_lib_char_dev.o
diff --git a/lib/ml-lib/test_driver/README.md b/lib/ml-lib/test_driver/README.md
new file mode 100644
index 000000000000..0bb4105c8aa4
--- /dev/null
+++ b/lib/ml-lib/test_driver/README.md
@@ -0,0 +1,233 @@
+# ML Library Testing Device Driver (mllibdev)
+
+ML library testing character device driver for the Linux kernel:
+- Basic read/write operations
+- IOCTL interface for device control
+- Sysfs attributes for runtime information
+- Procfs entry for debugging
+
+## Features
+
+### Character Device Operations
+- **Open/Close**: Device can be opened and closed multiple times
+- **Read**: Read data from a kernel buffer
+- **Write**: Write data to a kernel buffer (1KB capacity)
+- **Seek**: Support for lseek() operations
+
+### IOCTL Commands
+- `ML_LIB_TEST_DEV_IOCRESET`: Clear the device buffer
+- `ML_LIB_TEST_DEV_IOCGETSIZE`: Get current data size
+- `ML_LIB_TEST_DEV_IOCSETSIZE`: Set data size
+
+### Sysfs Attributes
+Located at `/sys/class/ml_lib_test/mllibdev`:
+- `buffer_size`: Maximum buffer capacity (read-only)
+- `data_size`: Current amount of data in buffer (read-only)
+- `access_count`: Number of times device has been opened (read-only)
+- `stats`: Comprehensive statistics (opens, reads, writes)
+
+### Procfs Entry
+Located at `/proc/mllibdev`: Provides formatted driver information
+
+## Building the Driver
+
+### Option 1: Build as a Module
+
+1. Configure the kernel to build mllibdev as a module:
+   ```bash
+   make menuconfig
+   # Navigate to: Library routines -> ML library testing character device driver
+   # Select: <M> ML library testing character device driver
+   ```
+
+2. Build the module:
+   ```bash
+   make -j$(nproc) M=lib/ml-lib/test_driver
+   ```
+
+### Option 2: Build into Kernel
+
+1. Configure the kernel:
+   ```bash
+   make menuconfig
+   # Navigate to: Library routines -> ML library testing character device driver
+   # Select: <*> ML library testing character device driver
+   ```
+
+2. Build the kernel:
+   ```bash
+   make -j$(nproc)
+   ```
+
+### Option 3: Quick Module Build (Out-of-Tree)
+
+For quick testing, you can build just the module:
+
+```bash
+cd lib/ml-lib/test_driver
+make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
+```
+
+## Loading the Driver
+
+If built as a module:
+
+```bash
+# Load the module
+sudo insmod /lib/modules/$(uname -r)/build/lib/ml-lib/test_driver/ml_lib_test_dev.ko
+
+# Verify it's loaded
+sudo lsmod | grep ml_lib_test_dev
+
+# Check kernel messages
+sudo dmesg | tail -20
+```
+
+You should see messages like:
+```
+ml_lib_test_dev: Initializing driver
+ml_lib_test_dev: Device number allocated: XXX:0
+ml_lib_test_dev: Driver initialized successfully
+ml_lib_test_dev: Device created at /dev/mllibdev
+ml_lib_test_dev: Proc entry created at /proc/mllibdev
+```
+
+## Testing the Driver
+
+### Quick Manual Test
+
+```bash
+# Write data to the device
+sudo su
+echo "Hello, kernel!" > /dev/mllibdev
+
+# Read data back
+sudo su
+cat /dev/mllibdev
+
+# Check sysfs attributes
+cat /sys/class/ml_lib_test/mllibdev/stats
+
+# Check proc entry
+cat /proc/mllibdev
+```
+
+### Using the Test Program
+
+1. Compile the test program:
+   ```bash
+   cd lib/ml-lib/test_driver/test_application
+   gcc -o ml_lib_test_dev test_ml_lib_char_dev.c
+   ```
+
+2. Run the test program:
+   ```bash
+   sudo ./ml_lib_test_dev
+   ```
+
+The test program will:
+- Open the device
+- Write test data
+- Read the data back
+- Test all IOCTL commands
+- Display sysfs attributes
+- Show procfs information
+
+### Example Test Output
+
+```
+ML Library Testing Device Driver Test Program
+==================================
+Device opened successfully: /dev/mllibdev
+
+========== Write Test ==========
+Successfully wrote 62 bytes
+Data: "Hello from userspace! This is a test of the mllibdev driver."
+
+========== Read Test ==========
+Successfully read 62 bytes
+Data: "Hello from userspace! This is a test of the mllibdev driver."
+
+========== IOCTL Tests ==========
+Current data size: 62 bytes
+Set data size to: 50 bytes
+Verified new size: 50 bytes
+Buffer reset successfully
+Size after reset: 0 bytes
+
+========== Sysfs Attributes ==========
+buffer_size: 1024
+data_size: 0
+access_count: 1
+
+stats: Opens: 1
+Reads: 1
+Writes: 1
+
+========== Procfs Information ==========
+ML Library Testing Device Driver Information
+=================================
+Device name:     mllibdev
+Buffer size:     1024 bytes
+Data size:       0 bytes
+Access count:    1
+Read count:      1
+Write count:     1
+
+========== Final Test ==========
+All tests completed successfully!
+```
+
+## Unloading the Driver
+
+```bash
+# Remove the module
+sudo rmmod ml_lib_test_dev
+
+# Verify it's unloaded
+sudo lsmod | grep ml_lib_test_dev
+
+# Check cleanup messages
+sudo dmesg | tail -10
+```
+
+## Troubleshooting
+
+### Device node doesn't exist
+```bash
+# Check if udev created the device
+ls -l /dev/mllibdev
+
+# Manually create if needed (shouldn't be necessary)
+sudo mknod /dev/mllibdev c MAJOR MINOR
+```
+
+### Permission denied
+```bash
+# Run commands with sudo
+sudo cat /dev/mllibdev
+
+# Or change permissions
+sudo chmod 666 /dev/mllibdev
+```
+
+### Module won't load
+```bash
+# Check kernel messages for errors
+dmesg | tail -20
+
+# Verify module dependencies
+modinfo lib/ml-lib/test_driver/ml_lib_test_dev.ko
+```
+
+## License
+
+This driver is licensed under GPL-2.0.
+
+## Author
+
+Viacheslav Dubeyko <slava@...eyko.com>
+
+## Version
+
+1.0
diff --git a/lib/ml-lib/test_driver/ml_lib_char_dev.c b/lib/ml-lib/test_driver/ml_lib_char_dev.c
new file mode 100644
index 000000000000..b2d6e27ece28
--- /dev/null
+++ b/lib/ml-lib/test_driver/ml_lib_char_dev.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Machine Learning (ML) library
+ * Testing Character Device Driver
+ *
+ * Copyright (C) 2025-2026 Viacheslav Dubeyko <slava@...eyko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mutex.h>
+#include <linux/ml-lib/ml_lib.h>
+
+#define DEVICE_NAME "mllibdev"
+#define CLASS_NAME "ml_lib_test"
+#define BUFFER_SIZE 1024
+
+/* IOCTL commands */
+#define ML_LIB_TEST_DEV_IOC_MAGIC   'M'
+#define ML_LIB_TEST_DEV_IOCRESET    _IO(ML_LIB_TEST_DEV_IOC_MAGIC, 0)
+#define ML_LIB_TEST_DEV_IOCGETSIZE  _IOR(ML_LIB_TEST_DEV_IOC_MAGIC, 1, int)
+#define ML_LIB_TEST_DEV_IOCSETSIZE  _IOW(ML_LIB_TEST_DEV_IOC_MAGIC, 2, int)
+
+/* Device data structure */
+struct ml_lib_test_dev_data {
+	struct cdev cdev;
+	struct device *device;
+	char *dataset_buf;
+	size_t dataset_buf_size;
+	size_t dataset_size;
+	char *recommendations_buf;
+	size_t recommendations_buf_size;
+	size_t recommendations_size;
+	struct mutex lock;
+	unsigned long access_count;
+	unsigned long read_count;
+	unsigned long write_count;
+
+	struct ml_lib_model *ml_model1;
+};
+
+#define ML_MODEL_1_NAME "ml_model1"
+
+static
+int ml_lib_test_dev_extract_dataset(struct ml_lib_model *ml_model,
+				    struct ml_lib_dataset *dataset);
+
+static struct ml_lib_dataset_operations ml_lib_test_dev_dataset_ops = {
+	.extract = ml_lib_test_dev_extract_dataset,
+};
+
+static dev_t dev_number;
+static struct class *ml_lib_test_dev_class;
+static struct ml_lib_test_dev_data *dev_data;
+static struct proc_dir_entry *proc_entry;
+
+/* ML model operations */
+static
+int ml_lib_test_dev_extract_dataset(struct ml_lib_model *ml_model,
+				    struct ml_lib_dataset *dataset)
+{
+	struct ml_lib_test_dev_data *data =
+		(struct ml_lib_test_dev_data *)ml_model->parent->private;
+	u8 pattern;
+
+	mutex_lock(&data->lock);
+	get_random_bytes(&pattern, 1);
+	memset(data->dataset_buf, pattern, data->dataset_buf_size);
+	data->dataset_size = data->dataset_buf_size;
+	atomic_set(&dataset->type, ML_LIB_MEMORY_STREAM_DATASET);
+	atomic_set(&dataset->state, ML_LIB_DATASET_CLEAN);
+	dataset->allocated_size = data->dataset_buf_size;
+	dataset->portion_offset = 0;
+	dataset->portion_size = data->dataset_buf_size;
+	mutex_unlock(&data->lock);
+
+	return 0;
+}
+
+/* File operations */
+static int ml_lib_test_dev_open(struct inode *inode, struct file *file)
+{
+	struct ml_lib_test_dev_data *data = container_of(inode->i_cdev,
+						struct ml_lib_test_dev_data,
+						cdev);
+
+	file->private_data = data;
+
+	mutex_lock(&data->lock);
+	data->access_count++;
+	mutex_unlock(&data->lock);
+
+	pr_info("ml_lib_test_dev: Device opened (total opens: %lu)\n",
+		data->access_count);
+
+	return 0;
+}
+
+static int ml_lib_test_dev_release(struct inode *inode, struct file *file)
+{
+	pr_info("ml_lib_test_dev: Device closed\n");
+	return 0;
+}
+
+static ssize_t ml_lib_test_dev_read(struct file *file, char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct ml_lib_test_dev_data *data = file->private_data;
+	size_t to_read;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	if (*ppos >= data->dataset_size) {
+		mutex_unlock(&data->lock);
+		return 0;
+	}
+
+	to_read = min(count, data->dataset_size - (size_t)*ppos);
+
+	ret = copy_to_user(buf, data->dataset_buf + *ppos, to_read);
+	if (ret) {
+		mutex_unlock(&data->lock);
+		return -EFAULT;
+	}
+
+	*ppos += to_read;
+	data->read_count++;
+
+	mutex_unlock(&data->lock);
+
+	pr_info("ml_lib_test_dev: Read %zu bytes\n", to_read);
+
+	return to_read;
+}
+
+static ssize_t ml_lib_test_dev_write(struct file *file, const char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct ml_lib_test_dev_data *data = file->private_data;
+	size_t to_write;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	if (*ppos >= data->recommendations_buf_size) {
+		mutex_unlock(&data->lock);
+		return -ENOSPC;
+	}
+
+	to_write = min(count, data->recommendations_buf_size - (size_t)*ppos);
+
+	ret = copy_from_user(data->recommendations_buf + *ppos, buf, to_write);
+	if (ret) {
+		mutex_unlock(&data->lock);
+		return -EFAULT;
+	}
+
+	*ppos += to_write;
+	if (*ppos > data->recommendations_size)
+		data->recommendations_size = *ppos;
+
+	data->write_count++;
+
+	mutex_unlock(&data->lock);
+
+	pr_info("ml_lib_test_dev: Wrote %zu bytes\n", to_write);
+
+	return to_write;
+}
+
+static long ml_lib_test_dev_ioctl(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct ml_lib_test_dev_data *data = file->private_data;
+	int size;
+
+	switch (cmd) {
+	case ML_LIB_TEST_DEV_IOCRESET:
+		mutex_lock(&data->lock);
+		memset(data->dataset_buf,
+			0, data->dataset_buf_size);
+		data->dataset_size = 0;
+		memset(data->recommendations_buf,
+			0, data->recommendations_buf_size);
+		data->recommendations_size = 0;
+		mutex_unlock(&data->lock);
+		pr_info("ml_lib_test_dev: Buffer reset via IOCTL\n");
+		break;
+
+	case ML_LIB_TEST_DEV_IOCGETSIZE:
+		mutex_lock(&data->lock);
+		size = data->dataset_size;
+		mutex_unlock(&data->lock);
+		if (copy_to_user((int __user *)arg, &size, sizeof(size)))
+			return -EFAULT;
+		break;
+
+	case ML_LIB_TEST_DEV_IOCSETSIZE:
+		if (copy_from_user(&size, (int __user *)arg, sizeof(size)))
+			return -EFAULT;
+		if (size < 0 || size > data->recommendations_buf_size)
+			return -EINVAL;
+		mutex_lock(&data->lock);
+		data->recommendations_size = size;
+		mutex_unlock(&data->lock);
+		pr_info("ml_lib_test_dev: Data size set to %d via IOCTL\n", size);
+		break;
+
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
+static const struct file_operations ml_lib_test_dev_fops = {
+	.owner = THIS_MODULE,
+	.open = ml_lib_test_dev_open,
+	.release = ml_lib_test_dev_release,
+	.read = ml_lib_test_dev_read,
+	.write = ml_lib_test_dev_write,
+	.unlocked_ioctl = ml_lib_test_dev_ioctl,
+	.llseek = default_llseek,
+};
+
+/* Sysfs attributes */
+static ssize_t buffer_size_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%zu\n", data->dataset_buf_size);
+}
+
+static ssize_t data_size_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+	size_t size;
+
+	mutex_lock(&data->lock);
+	size = data->dataset_size;
+	mutex_unlock(&data->lock);
+
+	return sprintf(buf, "%zu\n", size);
+}
+
+static ssize_t access_count_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", data->access_count);
+}
+
+static ssize_t stats_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct ml_lib_test_dev_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "Opens: %lu\nReads: %lu\nWrites: %lu\n",
+		       data->access_count, data->read_count,
+		       data->write_count);
+}
+
+static DEVICE_ATTR_RO(buffer_size);
+static DEVICE_ATTR_RO(data_size);
+static DEVICE_ATTR_RO(access_count);
+static DEVICE_ATTR_RO(stats);
+
+static struct attribute *ml_lib_test_dev_attrs[] = {
+	&dev_attr_buffer_size.attr,
+	&dev_attr_data_size.attr,
+	&dev_attr_access_count.attr,
+	&dev_attr_stats.attr,
+	NULL,
+};
+
+static const struct attribute_group ml_lib_test_dev_attr_group = {
+	.attrs = ml_lib_test_dev_attrs,
+};
+
+/* Procfs operations */
+static int ml_lib_test_dev_proc_show(struct seq_file *m, void *v)
+{
+	struct ml_lib_test_dev_data *data = dev_data;
+
+	seq_printf(m, "ML Library Testing Device Driver Information\n");
+	seq_printf(m, "=================================\n");
+	seq_printf(m, "Device name:     %s\n", DEVICE_NAME);
+	seq_printf(m, "Buffer size:     %zu bytes\n", data->dataset_buf_size);
+	seq_printf(m, "Data size:       %zu bytes\n", data->dataset_size);
+	seq_printf(m, "Access count:    %lu\n", data->access_count);
+	seq_printf(m, "Read count:      %lu\n", data->read_count);
+	seq_printf(m, "Write count:     %lu\n", data->write_count);
+
+	return 0;
+}
+
+static int ml_lib_test_dev_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ml_lib_test_dev_proc_show, NULL);
+}
+
+static const struct proc_ops ml_lib_test_dev_proc_ops = {
+	.proc_open = ml_lib_test_dev_proc_open,
+	.proc_read = seq_read,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+/* Module initialization */
+static int __init ml_lib_test_dev_init(void)
+{
+	struct ml_lib_model_options *options;
+	int ret;
+
+	pr_info("ml_lib_test_dev: Initializing driver\n");
+
+	/* Allocate device data */
+	dev_data = kzalloc(sizeof(struct ml_lib_test_dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	/* Allocate dataset buffer */
+	dev_data->dataset_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+	if (!dev_data->dataset_buf) {
+		ret = -ENOMEM;
+		goto err_free_data;
+	}
+
+	dev_data->dataset_buf_size = BUFFER_SIZE;
+	dev_data->dataset_size = 0;
+
+	/* Allocate recomendations buffer */
+	dev_data->recommendations_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+	if (!dev_data->recommendations_buf) {
+		ret = -ENOMEM;
+		goto err_free_dataset_buffer;
+	}
+
+	dev_data->recommendations_buf_size = BUFFER_SIZE;
+	dev_data->recommendations_size = 0;
+
+	mutex_init(&dev_data->lock);
+
+	/* Allocate device number */
+	ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME);
+	if (ret < 0) {
+		pr_err("ml_lib_test_dev: Failed to allocate device number\n");
+		goto err_free_recommendations_buffer;
+	}
+
+	pr_info("ml_lib_test_dev: Device number allocated: %d:%d\n",
+		MAJOR(dev_number), MINOR(dev_number));
+
+	/* Create device class */
+	ml_lib_test_dev_class = class_create(CLASS_NAME);
+	if (IS_ERR(ml_lib_test_dev_class)) {
+		ret = PTR_ERR(ml_lib_test_dev_class);
+		pr_err("ml_lib_test_dev: Failed to create class\n");
+		goto err_unregister_chrdev;
+	}
+
+	/* Initialize and add cdev */
+	cdev_init(&dev_data->cdev, &ml_lib_test_dev_fops);
+	dev_data->cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&dev_data->cdev, dev_number, 1);
+	if (ret < 0) {
+		pr_err("ml_lib_test_dev: Failed to add cdev\n");
+		goto err_class_destroy;
+	}
+
+	/* Create device */
+	dev_data->device = device_create(ml_lib_test_dev_class,
+					 NULL, dev_number,
+					 dev_data, DEVICE_NAME);
+	if (IS_ERR(dev_data->device)) {
+		ret = PTR_ERR(dev_data->device);
+		pr_err("ml_lib_test_dev: Failed to create device\n");
+		goto err_cdev_del;
+	}
+
+	/* Create sysfs attributes */
+	ret = sysfs_create_group(&dev_data->device->kobj,
+				 &ml_lib_test_dev_attr_group);
+	if (ret < 0) {
+		pr_err("ml_lib_test_dev: Failed to create sysfs group\n");
+		goto err_device_destroy;
+	}
+
+	/* Create procfs entry */
+	proc_entry = proc_create(DEVICE_NAME, 0444, NULL,
+				 &ml_lib_test_dev_proc_ops);
+	if (!proc_entry) {
+		pr_err("ml_lib_test_dev: Failed to create proc entry\n");
+		ret = -ENOMEM;
+		goto err_sysfs_remove;
+	}
+
+	dev_data->ml_model1 = allocate_ml_model(sizeof(struct ml_lib_model),
+						GFP_KERNEL);
+	if (IS_ERR(dev_data->ml_model1)) {
+		ret = PTR_ERR(dev_data->ml_model1);
+		pr_err("ml_lib_test_dev: Failed to allocate ML model\n");
+		goto err_procfs_remove;
+	} else if (!dev_data->ml_model1) {
+		ret = -ENOMEM;
+		pr_err("ml_lib_test_dev: Failed to allocate ML model\n");
+		goto err_procfs_remove;
+	}
+
+	ret = ml_model_create(dev_data->ml_model1, CLASS_NAME,
+			      ML_MODEL_1_NAME, &dev_data->device->kobj);
+	if (ret < 0) {
+		pr_err("ml_lib_test_dev: Failed to create ML model\n");
+		goto err_ml_model_free;
+	}
+
+	dev_data->ml_model1->parent->private = dev_data;
+	dev_data->ml_model1->model_ops = NULL;
+	dev_data->ml_model1->dataset_ops = &ml_lib_test_dev_dataset_ops;
+
+	options = allocate_ml_model_options(sizeof(struct ml_lib_model_options),
+					    GFP_KERNEL);
+	if (IS_ERR(options)) {
+		ret = PTR_ERR(options);
+		pr_err("ml_lib_test_dev: Failed to allocate ML model options\n");
+		goto err_ml_model_destroy;
+	} else if (!options) {
+		ret = -ENOMEM;
+		pr_err("ml_lib_test_dev: Failed to allocate ML model options\n");
+		goto err_ml_model_destroy;
+	}
+
+	ret = ml_model_init(dev_data->ml_model1, options);
+	if (ret < 0) {
+		pr_err("ml_lib_test_dev: Failed to init ML model\n");
+		goto err_ml_model_options_free;
+	}
+
+	pr_info("ml_lib_test_dev: Driver initialized successfully\n");
+	pr_info("ml_lib_test_dev: Device created at /dev/%s\n",
+		DEVICE_NAME);
+	pr_info("ml_lib_test_dev: Proc entry created at /proc/%s\n",
+		DEVICE_NAME);
+
+	return 0;
+
+err_ml_model_options_free:
+	free_ml_model_options(options);
+err_ml_model_destroy:
+	ml_model_destroy(dev_data->ml_model1);
+err_ml_model_free:
+	free_ml_model(dev_data->ml_model1);
+err_procfs_remove:
+	proc_remove(proc_entry);
+err_sysfs_remove:
+	sysfs_remove_group(&dev_data->device->kobj,
+			   &ml_lib_test_dev_attr_group);
+err_device_destroy:
+	device_destroy(ml_lib_test_dev_class, dev_number);
+err_cdev_del:
+	cdev_del(&dev_data->cdev);
+err_class_destroy:
+	class_destroy(ml_lib_test_dev_class);
+err_unregister_chrdev:
+	unregister_chrdev_region(dev_number, 1);
+err_free_recommendations_buffer:
+	kfree(dev_data->recommendations_buf);
+err_free_dataset_buffer:
+	kfree(dev_data->dataset_buf);
+err_free_data:
+	kfree(dev_data);
+	return ret;
+}
+
+/* Module cleanup */
+static void __exit ml_lib_test_dev_exit(void)
+{
+	pr_info("ml_lib_test_dev: Cleaning up driver\n");
+
+	/* Destroy ML model */
+	ml_model_destroy(dev_data->ml_model1);
+	free_ml_model(dev_data->ml_model1);
+
+	/* Remove procfs entry */
+	proc_remove(proc_entry);
+
+	/* Remove sysfs attributes */
+	sysfs_remove_group(&dev_data->device->kobj,
+			   &ml_lib_test_dev_attr_group);
+
+	/* Destroy device */
+	device_destroy(ml_lib_test_dev_class, dev_number);
+
+	/* Delete cdev */
+	cdev_del(&dev_data->cdev);
+
+	/* Destroy class */
+	class_destroy(ml_lib_test_dev_class);
+
+	/* Unregister device number */
+	unregister_chrdev_region(dev_number, 1);
+
+	/* Free buffers */
+	kfree(dev_data->recommendations_buf);
+	kfree(dev_data->dataset_buf);
+	kfree(dev_data);
+
+	pr_info("ml_lib_test_dev: Driver removed successfully\n");
+}
+
+module_init(ml_lib_test_dev_init);
+module_exit(ml_lib_test_dev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Viacheslav Dubeyko <slava@...eyko.com>");
+MODULE_DESCRIPTION("ML libraray testing character device driver");
+MODULE_VERSION("1.0");
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ