segfault while trying to upgrade kernel module to 2.6 char-dev-driver API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




attached is a cut-down patch that attempts to convert scx200_gpio
to use the new 2.6 char-dev-driver API.
Its closely modelled after LDD-3 scull driver.

it segfaults reliably on cat /proc/devices after rmmod'g
tested against 12-rc4-mm2, I think it will apply to 12-rc[45]


#!/bin/bash

# load 1 at a time ??
modprobe scx200
modprobe scx200_gpio

cat /proc/devices

rmmod scx200_gpio
cat /proc/devices    # 1st segfault here

rmmod scx200
cat /proc/devices    # segfault again here


I can hazard a few (blind) guesses as to the reasons for segfault:

1.  Im doing it wrong (I did check for the obvious, but..)
2.  this is a mixed conversion
scx200_gpio depends upon scx200, which is still old api, I havent touched it.

tia
jimc
diff -ruN -X exclude-diffs lnx/drivers/char/scx200_gpio.c scx200-segfault/drivers/char/scx200_gpio.c
--- lnx/drivers/char/scx200_gpio.c	2005-05-05 22:35:40.000000000 -0600
+++ scx200-segfault/drivers/char/scx200_gpio.c	2005-05-30 08:45:38.000000000 -0600
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/cdev.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -22,10 +23,21 @@
 MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver");
 MODULE_LICENSE("GPL");
 
+static int minor = 0;
 static int major = 0;		/* default to dynamic major */
 module_param(major, int, 0);
 MODULE_PARM_DESC(major, "Major device number");
 
+// int nr_devs = 1;
+#define NR_DEVS 1
+#define MAX_MINORS 96
+
+struct gpio_dev {
+       void *data;
+        struct cdev cdev;         /* Char device structure */
+}
+gpio_devices[NR_DEVS];
+
 static ssize_t scx200_gpio_write(struct file *file, const char __user *data, 
 				 size_t len, loff_t *ppos)
 {
@@ -109,9 +121,22 @@
 	.release = scx200_gpio_release,
 };
 
+static void scx200_setup_cdev(struct gpio_dev *dev, struct file_operations *fops, int index)
+{
+        int err, devno = MKDEV(major, minor + index);
+	
+        cdev_init(&dev->cdev, fops);
+        dev->cdev.owner = THIS_MODULE;
+        dev->cdev.ops = fops;
+        err = cdev_add (&dev->cdev, devno, 1);
+        /* Fail gracefully if need be */
+        if (err)
+                printk(KERN_NOTICE "Error %d adding %s %d", err, NAME, index);
+}
+
 static int __init scx200_gpio_init(void)
 {
-	int r;
+	int rc, i, devno = 0;
 
 	printk(KERN_DEBUG NAME ": NatSemi SCx200 GPIO Driver\n");
 
@@ -119,23 +144,38 @@
 		printk(KERN_ERR NAME ": no SCx200 gpio pins available\n");
 		return -ENODEV;
 	}
+	// scx200_init_shadow();
+	// from LDD-3
+	if (major) {
+                devno = MKDEV(major, minor);
+                rc = register_chrdev_region(devno, NR_DEVS, NAME);
+        } else {
+                rc = alloc_chrdev_region(&devno, minor, NR_DEVS, NAME);
+                major = MAJOR(devno);
+        }
+        if (rc < 0) {
+                printk(KERN_WARNING NAME ": can't get major %d\n", major);
+                return rc;
+        }
 
-	r = register_chrdev(major, NAME, &scx200_gpio_fops);
-	if (r < 0) {
-		printk(KERN_ERR NAME ": unable to register character device\n");
-		return r;
-	}
-	if (!major) {
-		major = r;
-		printk(KERN_DEBUG NAME ": got dynamic major %d\n", major);
-	}
+	
+	/* Initialize each device. */
+        for (i = 0; i < NR_DEVS; i++) {
+                scx200_setup_cdev(&gpio_devices[i], &scx200_gpio_fops, i);
+        }
 
 	return 0;
 }
 
 static void __exit scx200_gpio_cleanup(void)
 {
-	unregister_chrdev(major, NAME);
+	int i;
+        dev_t devno = MKDEV(major, minor);
+	
+	for (i = 0; i < NR_DEVS; i++) {
+		cdev_del(&gpio_devices[i].cdev);
+	}
+	unregister_chrdev_region(devno, MAX_MINORS);
 }
 
 module_init(scx200_gpio_init);

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux