Messages in this thread | | | Date | Wed, 8 Dec 1999 08:53:44 -0500 | From | Olivier Galibert <> | Subject | problem with unregister_chrdev in 2.3.30 ? |
| |
I'm writing a minimalist module driver to play with a dsp card. insmod goes nicely, rmmod _seems_ to go nicely, but them cat /proc/devices generates an oops:
Dec 8 08:43:11 athena kernel: IIADC64 minimal kernel driver (c) 1999 Olivier Galibert Dec 8 08:43:11 athena kernel: iiadc64: DSP board found, io at 0xd800, irq 9 Dec 8 08:43:15 athena kernel: iiadc64: Reset successful Dec 8 08:43:39 athena kernel: Unable to handle kernel paging request at virtual address cc4106ab Dec 8 08:43:39 athena kernel: printing eip: Dec 8 08:43:39 athena kernel: c0211ed5 Dec 8 08:43:39 athena kernel: *pde = 0135e063 Dec 8 08:43:39 athena kernel: *pte = 00000000 Dec 8 08:43:39 athena kernel: Oops: 0000 Dec 8 08:43:39 athena kernel: CPU: 0 Dec 8 08:43:39 athena kernel: EIP: 0010:[vsprintf+477/988] Dec 8 08:43:39 athena kernel: EFLAGS: 00010297 Dec 8 08:43:39 athena kernel: eax: cc4106ab ebx: ffffffff ecx: cc4106ab edx: fffffffe Dec 8 08:43:39 athena kernel: esi: ffffffff edi: ca7cd063 ebp: ca9dff38 esp: ca9dfef8 Dec 8 08:43:39 athena kernel: ds: 0018 es: 0018 ss: 0018 Dec 8 08:43:39 athena kernel: Process cat (pid: 855, stackpage=ca9df000) Dec 8 08:43:39 athena kernel: Stack: ca7cd000 c0270e44 0000004e c021f473 00000000 00000000 0000000a c02120e8 Dec 8 08:43:39 athena kernel: ca7cd05f c021f405 ca9dff30 c0129403 ca7cd05f c021f400 00000079 cc4106ab Dec 8 08:43:39 athena kernel: 00000c00 00000000 ca7cd000 ca7cd000 c0153aad ca7cd000 cb11de1c 00000c00 Dec 8 08:43:39 athena kernel: Call Trace: [tvecs+24743/33588] [sprintf+20/4896] [tvecs+24633/33588] [get_device_list+67/168] [tvecs+24628/33588] [<cc4106ab>] [devices_read_proc+21/72] Dec 8 08:43:39 athena kernel: [proc_file_read+274/564] [sys_read+189/220] [system_call+52/56] Dec 8 08:43:39 athena kernel: Code: 80 38 00 74 07 40 4a 83 fa ff 75 f4 29 c8 89 c6 8b 44 24 1c
OG. #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/ioport.h> #include <linux/sched.h> #include <linux/malloc.h> #include <linux/ioport.h> #include <linux/fcntl.h> #include <linux/delay.h> #include <linux/pci.h>
#include <asm/io.h> #include <asm/segment.h> #include <asm/system.h> #include <asm/ptrace.h>
#define DEBUG_AL(format, a...) printk(KERN_WARNING format, ##a) #define DEBUG_ER(format, a...) printk(KERN_WARNING format, ##a) #define DEBUG_WR(format, a...) printk(KERN_WARNING format, ##a) #define DEBUG_IN(format, a...) printk(KERN_WARNING format, ##a) #define DEBUG_TR(format, a...) printk(KERN_WARNING format, ##a)
static int iiadc64_open(struct inode *, struct file *); static int iiadc64_release(struct inode *, struct file *); static int iiadc64_ioctl(struct inode *, struct file *, unsigned int, unsigned long); static ssize_t iiadc64_read(struct file *, char *, size_t, loff_t *); static ssize_t iiadc64_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations iiadc64_fops = { 0, /* llseek */ 0, /* read */ 0, /* write */ 0, /* readdir */ 0, /* poll */ 0/*iiadc64_ioctl*/,/* ioctl */ 0, /* mmap */ iiadc64_open, /* open */ 0, /* flush */ iiadc64_release, /* release */ 0, /* fsync */ 0, /* fasync */ 0, /* check_media_change */ 0, /* revalidate */ 0 /* lock */ };
struct iiadc64_state { struct pci_dev *dev; unsigned long iobase; unsigned int irq; unsigned long memory; } is;
static unsigned int iiadc64_mailbox_read(int box) { int counter = 100000; int mask = 0xf0000 << box; while(!(inl(is.iobase + 0x34) & mask) && (--counter)); if(!counter) DEBUG_ER("iiadc64: Timeout on mailbox %d read\n", box); return inl(is.iobase + 0x10 + 4*box); }
static int iiadc64_mailbox_check_read(int box) { int mask = 0xf0000 << box; return (inl(is.iobase + 0x34) & mask) != 0; }
static void iiadc64_mailbox_write(int box, unsigned int data) { int counter = 100000; int mask = 0xf << box; while((inl(is.iobase + 0x34) & mask) && (--counter)); if(!counter) DEBUG_ER("iiadc64: Timeout on mailbox %d write\n", box); outl(data, is.iobase + 4*box); }
static void iiadc64_reset(void) { unsigned int intcsr; unsigned int timeout; unsigned int val;
intcsr = inl(is.iobase + 0x38); outl(intcsr & 0xfcffffff, is.iobase + 0x38); outl(0x0f000000, is.iobase + 0x3c); timeout = 2*HZ; do { current->state = TASK_INTERRUPTIBLE; timeout = schedule_timeout(timeout); } while (timeout); outl(0x00000000, is.iobase + 0x3c); timeout = 2*HZ; do { current->state = TASK_INTERRUPTIBLE; timeout = schedule_timeout(timeout); } while (timeout);
val = iiadc64_mailbox_read(0); if(val != 0x1f) DEBUG_ER("iiadc64: Wrong value in mailbox 0 after reset : %08x\n", val); else DEBUG_IN("iiadc64: Reset successful\n");
while(iiadc64_mailbox_check_read(0)) (void)iiadc64_mailbox_read(0); }
static int iiadc64_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; DEBUG_IN("iiadc64: open\n");
return 0; }
static int iiadc64_release(struct inode *inode, struct file *file) { DEBUG_IN("iiadc64: close\n"); MOD_DEC_USE_COUNT; return 0; }
#ifdef MODULE int init_module(void) #else int iiadc64_init(void) #endif { DEBUG_AL("IIADC64 minimal kernel driver (c) 1999 Olivier Galibert\n");
is.dev = pci_find_device(0x10e8, 0x807f, 0); if(!is.dev) { DEBUG_ER("iiadc64: Unable to find the DSP board\n"); return -EIO; }
is.iobase = is.dev->resource[0].start; is.irq = is.dev->irq; is.memory = get_free_page(GFP_KERNEL);
if (register_chrdev(121, "iiadc64", &iiadc64_fops)) { DEBUG_ER("iiadc64: Unable to register character device\n"); return -EIO; }
DEBUG_IN("iiadc64: DSP board found, io at 0x%lx, irq %u\n", is.iobase, is.irq);
iiadc64_reset();
return 0; }
#ifdef MODULE void cleanup_module(void) { free_page(is.memory); unregister_chrdev(120, "iiadc64"); } #endif
| |