examples/kerneltest/kernel_module.c
author Laurent Bessard
Wed, 05 Dec 2012 15:42:41 +0100
changeset 763 504ce1e3e94a
parent 467 40efa79d27dd
permissions -rw-r--r--
Merged
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     1
#include <linux/module.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     2
#include <linux/kthread.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     3
#include <linux/fs.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     4
#include <linux/cdev.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     5
#include <asm/uaccess.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     6
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     7
#include "TestMasterSlave.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     8
#include "console/console.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     9
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    10
#define minor 0
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    11
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    12
MODULE_LICENSE("GPL");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    13
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    14
static dev_t canftest_dev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    15
static struct cdev *canftest_cdev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    16
static struct task_struct *thread_start_p, *thread_stop_p;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    17
static DECLARE_MUTEX (canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    18
static int canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    19
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    20
int thread_start (void* data);
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    21
int thread_stop (void* data);
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    22
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    23
// handler processing write() requests from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    24
ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    25
		       loff_t *f_pos)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    26
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    27
	int cmd;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    28
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    29
	// get integer from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    30
	if (get_user (cmd, buf))
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    31
		return -EFAULT;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    32
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    33
	// process integer as command
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    34
	switch (cmd) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    35
		case CMD_START:
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    36
			if (!canftest_stopped) break;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    37
			thread_start_p = kthread_create (thread_start, NULL, "canftest_start");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    38
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    39
			if (PTR_ERR(thread_start_p) == -ENOMEM) {
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    40
				printk(KERN_WARNING "canftest: error creating start thread\n");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    41
				return -ENOMEM;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    42
			}
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    43
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    44
			wake_up_process (thread_start_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    45
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    46
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    47
		case CMD_STOP:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    48
			if (canftest_stopped) break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    49
			thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    50
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    51
			if (PTR_ERR(thread_stop_p) == -ENOMEM) {
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    52
				printk(KERN_WARNING "canftest: error creating stop thread\n");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    53
				return -ENOMEM;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    54
			}
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    55
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    56
			wake_up_process (thread_stop_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    57
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    58
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    59
		// ignore new line character
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    60
		case 10:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    61
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    62
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    63
		default:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    64
			printk("canftest: bad command %d\n", cmd);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    65
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    66
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    67
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    68
	return count;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    69
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    70
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    71
// register write() handler
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    72
static struct file_operations canftest_fops = {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    73
	.owner =    THIS_MODULE,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    74
	.write =    canftest_write,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    75
};
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    76
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    77
// start TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    78
int thread_start (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    79
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    80
	int ret=0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    81
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    82
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    83
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    84
	ret=TestMasterSlave_start();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    85
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    86
	// if started
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    87
	if (ret == 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    88
		canftest_stopped = 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    89
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    90
		// increment module usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    91
		try_module_get(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    92
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    93
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    94
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    95
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    96
	return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    97
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    98
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    99
// finish TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   100
int thread_stop (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   101
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   102
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   103
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   104
	TestMasterSlave_stop();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   105
	canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   106
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   107
	// decrement usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   108
	module_put(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   109
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   110
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   111
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   112
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   113
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   114
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   115
int init_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   116
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   117
	int ret, major;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   118
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   119
	// get major device number dynamically
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   120
	ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   121
	major = MAJOR(canftest_dev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   122
	if (ret < 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   123
		printk(KERN_WARNING "canftest: can't get major %d\n", major);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   124
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   125
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   126
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   127
	canftest_cdev = cdev_alloc( );
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   128
	canftest_cdev->owner = THIS_MODULE;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   129
	canftest_cdev->ops = &canftest_fops;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   130
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   131
	// register new character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   132
	ret = cdev_add (canftest_cdev, canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   133
	if (ret) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   134
		printk(KERN_WARNING "canftest: error %d adding char device\n", ret);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   135
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   136
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   137
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   138
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   139
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   140
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   141
void cleanup_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   142
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   143
	// unregister major device number and character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   144
	unregister_chrdev_region(canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   145
	cdev_del(canftest_cdev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   146
}