From: Thadeu Lima de Souza Cascardo Date: Tue, 8 Dec 2009 17:57:33 +0000 (-0200) Subject: Allocate buffers for any number of devices. X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fkernel%2Fsamples%2F02.char%2F.git;a=commitdiff_plain;h=039521d8d6979c17201080e1349aef039ed1c91a Allocate buffers for any number of devices. --- diff --git a/helloc.c b/helloc.c index 00ce97d..f43a767 100644 --- a/helloc.c +++ b/helloc.c @@ -13,37 +13,29 @@ MODULE_DESCRIPTION("A hello world char device"); MODULE_VERSION("1.0.0"); #define BUFFER_SIZE 4096 - -/* Message buffer we send to upstream */ -static char *hello_message; -static char *goodbye_message; +#define DEVICE_NUMBER 2 struct message { char *text; size_t len; }; +/* Message buffer we send to upstream */ +static struct message *hello_message[DEVICE_NUMBER]; + static int helloc_open(struct inode *ino, struct file *filp) { struct message *msg; printk(KERN_INFO "Opened file with minor %d\n", iminor(ino)); - msg = kmalloc(sizeof(struct message), GFP_KERNEL); - if (!msg) - return -ENOMEM; - if (iminor(ino) == 0) { - msg->text = hello_message; - msg->len = BUFFER_SIZE; - } else { - msg->text = goodbye_message; - msg->len = BUFFER_SIZE; - } + if (iminor(ino) >= DEVICE_NUMBER) + return -ENODEV; + msg = hello_message[iminor(ino)]; filp->private_data = msg; return 0; } static int helloc_release(struct inode *ino, struct file *filp) { - kfree(filp->private_data); return 0; } @@ -103,17 +95,45 @@ static struct file_operations helloc_fops = { static dev_t dev; static struct cdev *cdev; +static void helloc_free(void) +{ + int i; + for (i = 0; i < DEVICE_NUMBER; i++) { + if (hello_message[i]) + kfree(hello_message[i]->text); + kfree(hello_message[i]); + } +} + +static int __init helloc_alloc(void) +{ + int i; + for (i = 0; i < DEVICE_NUMBER; i++) { + hello_message[i] = kzalloc(sizeof(struct message), GFP_KERNEL); + if (!hello_message[i]) + goto out; + hello_message[i]->text = kzalloc(BUFFER_SIZE, GFP_KERNEL); + if (!hello_message[i]->text) + goto out; + } + return 0; +out: + for (; i >= 0; i--) { + if (hello_message[i]) + kfree(hello_message[i]->text); + kfree(hello_message[i]); + } + return -ENOMEM; +} + static int __init helloc_init(void) { - int r = -ENOMEM; + int r; + r = helloc_alloc(); + if (r) + goto out_alloc2; /* allocate any major number with only one minor */ - hello_message = kzalloc(BUFFER_SIZE, GFP_KERNEL); - if (!hello_message) - goto out_hello; - goodbye_message = kzalloc(BUFFER_SIZE, GFP_KERNEL); - if (!goodbye_message) - goto out_goodbye; - r = alloc_chrdev_region(&dev, 0, 2, "helloc"); + r = alloc_chrdev_region(&dev, 0, DEVICE_NUMBER, "helloc"); if (r) goto out_region; r = -ENOMEM; @@ -127,7 +147,7 @@ static int __init helloc_init(void) cdev->owner = THIS_MODULE; cdev->ops = &helloc_fops; /* register the chardev to the system */ - r = cdev_add(cdev, dev, 2); + r = cdev_add(cdev, dev, DEVICE_NUMBER); if (r) goto out_add; return 0; @@ -136,12 +156,9 @@ out_add: kfree(cdev); out_alloc: /* release the device number allocated */ - unregister_chrdev_region(dev, 2); + unregister_chrdev_region(dev, DEVICE_NUMBER); out_region: - kfree(goodbye_message); -out_goodbye: - kfree(hello_message); -out_hello: +out_alloc2: return r; } @@ -150,9 +167,8 @@ static void __exit helloc_exit(void) /* remove the chardev from the system */ cdev_del(cdev); /* release the device number allocated */ - unregister_chrdev_region(dev, 2); - kfree(goodbye_message); - kfree(hello_message); + unregister_chrdev_region(dev, DEVICE_NUMBER); + helloc_free(); } module_init(helloc_init);