Hello all,
I had a homebrew driver that compiled and ran well on 2.6.38 and I recently upgraded to the latest xilinx kernel and had some trouble recompiling without adjustments (of_driver/driver, of_platform_driver/platform_driver and some such).

But now, after those adjustments, it crashes on run.

My first generic question is: is there a clean canonical example of how to write each part (module init/exit, /dev handling, probing, physical memory access, interrupt handling, etc) of a basic driver ? Because each upgrade breaks my code and as driver writing is only one of my duties, I have a hard time keeping up with the moving target of the requirements... To say that books are obsolete is an understatement.

And now to the specifics:

[   16.655868] {xad_init 519} Module xad: loading...
[   16.661122] {xad_init 528} Module xad: Major=241, Minor=0, Count=1
[ 16.666231] Unable to handle kernel paging request for data at address 0x00000030
[   16.673599] Faulting instruction address: 0xc0116fc0
[   16.678495] Oops: Kernel access of bad area, sig: 11 [#1]
[   16.683745] Xilinx Virtex
[   16.686337] Modules linked in: xad(+)
[   16.689978] NIP: c0116fc0 LR: c939a0f8 CTR: c0116fa8
[   16.694912] REGS: c789fd90 TRAP: 0300   Not tainted  (3.0.0-14.1-build3+)
[   16.701629] MSR: 00029030 <EE,ME,CE,IR,DR>  CR: 42000022  XER: 20000000
[   16.708199] DEAR: 00000030, ESR: 00000000
[   16.712185] TASK = c7851420[281] 'insmod' THREAD: c789e000
[ 16.717441] GPR00: c939a0f8 c789fe40 c7851420 c9397b70 000046d7 ffffffff c0110314 00000000 [ 16.725736] GPR08: c0337380 00000000 00004000 c0116fa8 22000024 100b99d4 ffffffff ffffffff [ 16.734030] GPR16: ffffffff ffffffff 100b5aed bfa54388 100844d8 100844b8 000007a0 00000000 [ 16.742324] GPR24: c0047edc 00000124 0000001c c9390000 c93973da c9397b08 c93971e8 c9397b70
[   16.750870] NIP [c0116fc0] driver_register+0x18/0x144
[   16.755901] LR [c939a0f8] xad_init+0xf8/0x1e8 [xad]
[   16.760638] Call Trace:
[ 16.763119] [c789fe40] [c93973da] xad_device_id+0x1da/0xfffffef8 [xad] (unreliable)
[   16.770719] [c789fe60] [c939a0f8] xad_init+0xf8/0x1e8 [xad]
[   16.776230] [c789fe80] [c0002508] do_one_initcall+0xe0/0x1c0
[   16.781871] [c789feb0] [c004a08c] sys_init_module+0x15cc/0x17c0
[   16.787720] [c789ff40] [c000c95c] ret_from_syscall+0x0/0x3c
[   16.793212] Instruction dump:
[ 16.796155] 80630034 4bfcd669 80010014 38210010 7c0803a6 4e800020 9421ffe0 7c0802a6
[   16.803842] bf410008 90010024 7c7f1b78 81230004
[   16.808257]  7c000034 5400d97e 0f000000
[   16.813362] ---[ end trace e40dbcf43f9d5d57 ]---

I don't understand the part about address 0x00000030. Does it mean I'm trying to wrongly access physical/virtual address 0x30 somewhere in my code?

Here are the very basics from my code (I've removed all printk, error checking and what the driver itself does for clarity). I really need a hand with the changes of of_something:

static dev_t first;
static unsigned int count = 1;
static int my_major = 241, my_minor = 0;

struct cdev *my_cdev=NULL;

typedef struct XadDevice {
//      struct platform_device *of_dev;
        struct device *dev;
        int irq;
        resource_size_t hw_phy_base, hw_length; // Address of the IP resource
        void *hw_virt;                                                  // 
Virtual of above
#ifdef DEBUG
        void *buffer_virt;                                              // 
Virtual address of the above
#endif
        struct resource *hw_region;                             // Nothing is 
done with this
        ...
} tXadDevice;
tXadDevice Xad;


static irqreturn_t XadIsr(int irq, void *dev_id) { ... }

static int xad_driver_probe(struct device * dev)
        struct resource res;
        struct device_node *dn = dev->of_node;
        int rc=0;

        printk(KERN_INFO SD "Probing %s\n" FL, dn->full_name);

        rc = of_address_to_resource(dn, 0, &res);

        Xad.irq = irq_of_parse_and_map(dn, 0);
rc=request_irq(Xad.irq, XadIsr, IRQF_TRIGGER_RISING /* | IRQF_DISABLED*/ | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "XadIsr", &Xad);

        init_waitqueue_head(&Xad.wait);

Xad.hw_region = request_mem_region((unsigned int)Xad.hw_phy_base, (unsigned int)(Xad.hw_length), "xps-acqui-data");

Xad.hw_virt= ioremap( (unsigned int)Xad.hw_phy_base, (unsigned int)(Xad.hw_length) );

        dev_set_drvdata(Xad.dev, &Xad);
        return 0;
}


///////////////////////////////////////////////////////////////////////////////
// There should be something in:
// ll /sys/devices/plb.0/c9800000.xps-acqui-data
static const struct of_device_id xad_device_id[] = {
        { .compatible     = "xlnx,xps-acqui-data-4.00.a" },   // Must match the 
DTS
        {}
};

MODULE_DEVICE_TABLE(of, xad_device_id); // Is this necessary ?

static struct device_driver xad_driver = {
        .probe  = xad_driver_probe,
        .remove = xad_driver_remove,
        .name = "xad-driver",
        .of_match_table = xad_device_id,
};

...

static struct file_operations fops = {
        .owner   = THIS_MODULE,
        .read    = xad_read,
        .open    = xad_open,
        .release = xad_close,
        .unlocked_ioctl   = xad_ioctl,
};

static int __init xad_init(void) {
        first = MKDEV (my_major, my_minor);
        register_chrdev_region(first, count, DEVNAME);
        my_cdev = cdev_alloc ();
        
        cdev_init(my_cdev, &fops);
        rc=cdev_add (my_cdev, first, count);
        
        rc = driver_register(&xad_driver);

        printk(KERN_INFO SD "Driver ready!\n" FL);
        return 0;
}

module_init(xad_init);


Thanks for reading so far !!!
--
Guillaume Dargaud
http://www.gdargaud.net/
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to