Kernel panics : trying to write / read on tiny tty driver


 
Thread Tools Search this Thread
Operating Systems Linux Ubuntu Kernel panics : trying to write / read on tiny tty driver
# 1  
Old 05-14-2013
Kernel panics : trying to write / read on tiny tty driver

I'm a beginner to the Linux programming and trying my hands on some device driver examples while practising. The below code (a trimmed down version of tiny_tty.c from ldd3 book) loads perfectly using insmod and I'm able to see it in /proc/tty/drivers , /proc/modules and device nodes are getting created under /dev. When I try to write to device file like echo "abcd" > /dev/ttyms0 or read like cat /dev/ttyms0, the kernel panics with a call trace on the screen. I'm on kernel 3.5.0 under Ubuntu. Any help is very much appreciated.
I tried initializing the timer in open function and below is the call trace for "kernel panic - not syncing : fatal exception in interrupt panic occurred, switching back to text console".
Call trace I get when Kernel panics:

Quote:
update_sd_lb_stats+0xcd/0x4b0
find_busiest_group+0x2e/0x420
enqueue_entity+0xcb/0x510
load_balance+0x7e/0x5e0
rebalance_domains+0xed/0x150
__do_softirq+0xdb/0x180
local_bh_enable_ip+0x90/0x90
<IRQ>
copy_to_user0x41/0x60
sys_gettimeofday+0x2a/0x70
sysenter_do_call0x12/0x20
Below is the full code:

Code:
#include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/kdev_t.h>
    #include <linux/wait.h>
    #include <linux/errno.h>
    #include <linux/slab.h>     /* kmalloc() */
    #include <linux/tty_driver.h>
    #include <linux/tty.h>
    #include <linux/tty_flip.h>
    #include <linux/mutex.h>
    #include <linux/serial.h>
    #include <linux/sched.h>
    #include <asm/uaccess.h>
    #include <asm/termios.h>


    MODULE_LICENSE("GPL");

    #define MS_TTY_MAJOR 250    //test value
    #define MS_TTY_NUM_DEV 2
    #define DELAY_TIME      HZ * 2      /* 2 seconds per character */
    #define TINY_DATA_CHARACTER 't'

    static int major_num;
    //static int minor_num=0;
    //static int num_tty_dev=2;

    /* Below structure is a wrapper for device specific fields */
    struct ms_tty_serial {
        struct tty_struct   *tty;       /* pointer to the tty for this device */
        int         open_count; /* number of times this port has been opened */
        struct semaphore    sem;        /* locks this structure */
        struct timer_list   *timer;

    };

    static struct ms_tty_serial *ms_tty_table[MS_TTY_NUM_DEV];  /* initially all NULL */

    static void ms_tty_timer(unsigned long timer_data)
    {
        struct ms_tty_serial *ms_ptr = (struct ms_tty_serial *)timer_data;
        struct tty_struct *tty;
        char data[1] = {TINY_DATA_CHARACTER};


    int data_size = 1;

        if (!ms_ptr)
            return;

        tty = ms_ptr->tty;
        tty->low_latency=1;
        /* send the data to the tty layer for users to read.  This doesn't
         * actually push the data through unless tty->low_latency is set */
        tty_buffer_request_room (tty, data_size);
            tty_insert_flip_string(tty, data, data_size);
            tty_flip_buffer_push(tty);

        /* resubmit the timer again */
        ms_ptr->timer->expires = jiffies + DELAY_TIME;
        add_timer(ms_ptr->timer);
    }



    //// Define the open function ////

   static int tty_ms_open(struct tty_struct *tty_this, struct file *file_this)
{

    printk(KERN_ALERT "tty_ms driver: OPENED ...\n");
    struct ms_tty_serial *ms_ptr;
    struct timer_list *timer;
    int index;

    /* initialize the pointer in case something fails */
    tty_this->driver_data = NULL;

    /* get the serial object associated with this tty pointer */
    index = tty_this->index;
    ms_ptr = ms_tty_table[index];
    if (ms_ptr == NULL) {
        /* first time accessing this device, create it */
        ms_ptr = kmalloc(sizeof(*ms_ptr), GFP_KERNEL);
        if (!ms_ptr)
            return -ENOMEM;

//      init_MUTEX(&ms_ptr->sem);       /* didn't work for this kernel version 3.5.0 */

        #ifndef init_MUTEX      /* sema_init is to be used for kernel 2.6.37 and above */
        sema_init(&ms_ptr->sem,1);
        #else
        init_MUTEX(&ms_ptr->sem);
        #endif

        ms_ptr->open_count = 0;
        ms_ptr->timer = NULL;

        ms_tty_table[index] = ms_ptr;
    }

    down(&ms_ptr->sem);

    /* save our structure within the tty structure */
    tty_this->driver_data = ms_ptr;
    ms_ptr->tty = tty_this;
    ms_ptr->filp = file_this;       // to be tried
    ++ms_ptr->open_count;
    if (ms_ptr->open_count == 1) {
        /* this is the first time this port is opened */
        /* do any hardware initialization needed here */

        /* create timer and submit it */
        if (!ms_ptr->timer) {
            timer = kmalloc(sizeof(*timer), GFP_KERNEL);
            if (!timer) {
                up(&ms_ptr->sem);
                return -ENOMEM;
            }
            ms_ptr->timer = timer;
        }

        init_timer (ms_ptr->timer);     // to be tried
        ms_ptr->timer->data = (unsigned long )ms_ptr;
        ms_ptr->timer->expires = jiffies + DELAY_TIME;
        ms_ptr->timer->function = ms_tty_timer;
        add_timer(ms_ptr->timer);
    }

    up(&ms_ptr->sem);
    return 0;
}

    //// Define the close function ////

    static void do_close(struct ms_tty_serial *ms_ptr)
    {
        down(&ms_ptr->sem);

        if (!ms_ptr->open_count) {
            /* port was never opened */
            goto exit;
        }

        --ms_ptr->open_count;
        if (ms_ptr->open_count <= 0) {
            /* The port is being closed by the last user. */
            /* Do any hardware specific stuff here */

            /* shut down our timer */
            del_timer(ms_ptr->timer);
        }
    exit:
        up(&ms_ptr->sem);
    }

    static void tty_ms_close(struct tty_struct *tty_this, struct file *file_this)
    {

        printk(KERN_ALERT "tty_ms driver: CLOSING ...\n");
        struct ms_tty_serial *ms_ptr = tty_this->driver_data;

        if (ms_ptr)
            do_close(ms_ptr);
    }


    //// Define the write function ////

    static int tty_ms_write(struct tty_struct *tty_this, const unsigned char *tty_buff, int count)
    {

        printk(KERN_ALERT "tty_ms driver: WRITING ...\n");
    struct ms_tty_serial *ms_ptr = tty_this->driver_data;
        int i;
        int retval = -EINVAL;

        if (!ms_ptr)
            return -ENODEV;

        down(&ms_ptr->sem);

        if (!ms_ptr->open_count)
            /* port was not opened */
            {
            up(&ms_ptr->sem);
            return retval;
            }
        /* fake sending the data out a hardware port by
         * writing it to the kernel debug log.
         */
        printk(KERN_DEBUG "%s - ", __FUNCTION__);
        for (i = 0; i < count; ++i)
            printk("%02x ", tty_buff[i]);
        printk("\n");
        return 0;

    }

    // Define the operations for tty driver in tty_operations struct //

    static struct tty_operations tty_ms_ops = {
    .open = tty_ms_open,
    .close = tty_ms_close,
    .write = tty_ms_write,
    //.set_termios = tty_ms_set_termios,
    };

    ///////////////////////////////////////// Module Initialization Starts ////////////////////////////////////

    static struct tty_driver *tty_ms_driver;

    static int tty_ms_init(void)
    {
    //  static int result;
        static int retval,iter;

    // Allocate the tty_driver struct for this driver //

        tty_ms_driver = alloc_tty_driver(MS_TTY_NUM_DEV);
        if (!tty_ms_driver)
        return -ENOMEM;         // Error NO Memory , allocation failed
        else
        printk(KERN_INFO "tty_driver structure allocated..!!");     //debug line

    // Initialize the allocated tty_driver structure //
        tty_ms_driver->magic=TTY_DRIVER_MAGIC;
        tty_ms_driver->owner = THIS_MODULE;
        tty_ms_driver->driver_name = "tty_ms";
        tty_ms_driver->name = "ttyms";
        tty_ms_driver->major = MS_TTY_MAJOR,
        tty_ms_driver->type = TTY_DRIVER_TYPE_SERIAL,
        tty_ms_driver->subtype = SERIAL_TYPE_NORMAL,
        tty_ms_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,
        tty_ms_driver->init_termios = tty_std_termios;
        tty_ms_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
        tty_set_operations(tty_ms_driver, &tty_ms_ops);
        printk(KERN_INFO "allocated tty_driver structure -INITIALIZED.");   //debug line
    //// Register this driver with the tty core ////

        retval = tty_register_driver(tty_ms_driver);
        if (retval) {
        printk(KERN_ERR "failed to register tty_ms driver\n tty registration returned %d", retval);
        put_tty_driver(tty_ms_driver);
        return retval;
        }

    //// Register the tty devices(nodes) with the tty core ////

        for (iter = 0; iter < MS_TTY_NUM_DEV ; ++iter)
        tty_register_device(tty_ms_driver, iter, NULL);
        return 0;       // All initializations done

    }           // init func ends

    ///////////////////////////////////////// Module Initialization Ends ////////////////////////////////////

    ///////////////////////////////////////// Module cleanup Starts ////////////////////////////////////

    static void tty_ms_terminate(void)
    {
        static int iter;
        struct ms_tty_serial *tty_ser;
        printk(KERN_ALERT "tty_ms driver: Unloading...\n");

        for(iter=1;iter<=MS_TTY_NUM_DEV;iter++)
         tty_unregister_device(tty_ms_driver,iter);   //unregister all the devices, from tty layer 
        tty_unregister_driver(tty_ms_driver);       // Now unregister the driver from tty layer

        /* shut down all of the timers and free the memory */
        for (iter = 0; iter < MS_TTY_NUM_DEV; ++iter) {
            tty_ser = ms_tty_table[iter];
            if (tty_ser) {
                /* close the port */
                while (tty_ser->open_count)
                    do_close(tty_ser);

                /* shut down our timer and free the memory */
                del_timer(tty_ser->timer);
                kfree(tty_ser->timer);
                kfree(tty_ser);
                ms_tty_table[iter] = NULL;
            }
        }   

         dev_t devno=MKDEV(major_num,0);  // wrap major/minor numbers in a dev_t structure , to pass for deassigning.
         unregister_chrdev_region(devno,MS_TTY_NUM_DEV); 

    }

    ///////////////////////////////////////// Module cleanup ends ////////////////////////////////////

    module_init(tty_ms_init);
    module_exit(tty_ms_terminate);

# 2  
Old 05-14-2013
What'd you trim out?
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Old SGI Irix UNIX box kernel panics

I am relatively new to 'older unix' systems but I am hoping someone can help me with the error I am seeing on my box. We have an Irix 6.5 running. Our computer keeps restarting (crashed once) itself, by itself, at random points in the last 5 out of 8 sessions. This is the sys log, that i took a... (0 Replies)
Discussion started by: pmccpete
0 Replies

2. BSD

A question about BSD kernel and driver

I have an old hppa workstation install Openbsd on it,suppose i want to use bktr driver on it,i see bktr is configured on some archs(amd64,i386,ppc) but not on hppa,can i use the bktr driver line from amd64 or i386 in Generic kernel or custom kernel config? (3 Replies)
Discussion started by: Linusolaradm1
3 Replies

3. Shell Programming and Scripting

Read input from another tty

Hello, I am trying to find out how I can find the tty number of a terminal a bash script has just created. Ultimately what I am trying to achieve is a script that starts a new terminal where stderr can be directed to. ls -l missing_file 2> /dev/pts/X To find the tty number of the... (3 Replies)
Discussion started by: colinireland
3 Replies

4. Fedora

Is Kernel module is the same as a device driver?

I have been reading prep questions for my second unix academy exam, and there's a nuance, I'm not sure I understand it correctly. I've been under impression from my readings of book by Evi Nemeth and from unix academy DVDs I've been watching, that kernel's modules are drivers. I think of it, as... (25 Replies)
Discussion started by: newlinuxuser1
25 Replies

5. Solaris

Which file is read by kernel to set its default system kernel parameters values?

Hi gurus Could anybody tell me which file is read by kernel to set its default system kernal parameters values in solaris. Here I am not taking about /etc/system file which is used to load kernal modules or to change any default system kernal parameter value Is it /dev/kmem file or something... (1 Reply)
Discussion started by: girish.batra
1 Replies

6. IP Networking

read/write,write/write lock with smbclient fails

Hi, We have smb client running on two of the linux boxes and smb server on another linux system. During a backup operation which uses smb, read of a file was allowed while write to the same file was going on.Also simultaneous writes to the same file were allowed.Following are the settings in the... (1 Reply)
Discussion started by: swatidas11
1 Replies

7. Programming

Understanding read/write and kernel interaction

Ok, so I'm trying to finalize my understanding of read/write and kernel interaction. read(): You have a library function that has as it's first parameter (what the open file to read from is), second parameter( a pointer to a buffer (is this the location of a buffer in the user area or the... (7 Replies)
Discussion started by: Krothos
7 Replies

8. UNIX for Dummies Questions & Answers

Understanding read/write and kernel interaction

Ok, so I'm trying to finalize my understanding of read/write and kernel interaction. read(): You have a library function that has as it's first parameter (what the open file to read from is), second parameter( a pointer to a buffer (is this the location of a buffer in the user area or the... (1 Reply)
Discussion started by: Krothos
1 Replies

9. UNIX for Advanced & Expert Users

Kernel and Device Driver Programming

I am looking for a guide on how to program for either the Linux or FreeBSD (includes 4.4BSD, NetBSD or OpenBSD) kernel. I would prefer to learn how to write device drivers, but anything would help. If you know, please email me at *removed* or leave a post here Regards, Farhan (0 Replies)
Discussion started by: Farhan
0 Replies
Login or Register to Ask a Question