Hi, Greg KH, Thanks for the advices. Some questions inline.
-----Original Message----- From: 'Greg KH' <greg@kroah.com> Sent: Monday, April 11, 2022 11:26 PM To: Chan Kim <ckim@etri.re.kr> Cc: 'qemu-discuss' <qemu-discuss@nongnu.org>; kernelnewbies@kernelnewbies.org Subject: Re: Can't understand /proc/interrupts output for GICv3 case
On Mon, Apr 11, 2022 at 11:15:57PM +0900, Chan Kim wrote:
What bus type is your driver written for?
That sounds very logical. In my case I added it to system bus.
What exactly do you mean by "system bus"?
I meant 'sysbus' in qemu code that I showed in the qemu code. And I think it's the CPU bus.
Where is your kernel code?
This is the init function of my char driver. I thought if the struct cdev contains struct device, maybe I could use the struct device's of_node to call of_irq_get but it doesn't. And I remember I've seen the cdev in usually contained in the driver data of platform driver(?). Can I implement platform driver in kernel
module form?
Below is the char driver init code. Currently it's request_irq(6, ... ) but I want to know out the number 6 using program. If you have any advice, please tell me.
static int __init chr_driver_init(void) { int ret; /* Allocating Major number */ if ((alloc_chrdev_region(&dev, 0, 1, "axpu_Dev")) < 0) { printk(KERN_INFO"Cannot allocate the major number..\n"); return -1; }
printk(KERN_INFO"Major = %d Minor = %d..\n",MAJOR(dev),MINOR(dev));
/* creating cdev structure */ cdev_init(&axpu_cdev, &fops); axpu_cdev.owner = THIS_MODULE;
/* Adding character device to the system */ if ((cdev_add(&axpu_cdev,dev,1)) < 0) { printk(KERN_INFO "Cannot add the device to the system...\n"); goto r_class; }
/* creating struct class */ if ((dev_class = class_create(THIS_MODULE, "axpu_class")) == NULL) { printk(KERN_INFO "cannot create the struct class...\n"); goto r_class; }
/* for interrupt test !! */ /* for vanilla work-around.. already made by mkdev */ if ((device_create(dev_class, NULL, dev, NULL, "axpu_device")) == NULL) { printk(KERN_INFO "cannot create the device ..\n"); goto r_device; } else { printk(KERN_INFO "axpu_device created..\n"); } /**/
You can replace all of the above code by just using the miscdevice interface instead. Please use that, it ensures that you do everything properly and simplifies it all.
vaddr = ioremap(AXPU_BASE, 0x80000);
Wait, where are you picking those random values from?
Yes, it now looks weird to me. I have passed the register address information in the device tree and the kernel already knows my device's address range. Then, how should I get this virtual io address in this driver? I need it to access some registers. How can I ask the system bus? And my driver is a kernel module because I want to use it in ubuntu-20.04 on a virtual machine, I want it to be a kernel module that I can insmod or rmmod.(actually my job is to provide this virtual machine to some folks). And I cannot build the ubuntu image even if I change it to a platform device driver and add it in the kernel tree.
That's not how drivers work in the kernel. You have to have a bus pass you a device. Please register your driver with the proper bus type and go from there. The probe callback should be the place you set things up based on the device and resources given to you by the bus.
You can't just randomly pick memory locations and think things will work.
if(!vaddr) { printk(KERN_INFO"Failed to map the address.\n"); release_mem_region(AXPU_BASE,AXPU_SIZE); return 1; } printk("----- AXPU_BASE mapped at vaddr = %px\n", vaddr);
ret = request_irq(6, axpu_irq_handler, IRQF_SHARED, "axpu_irq", &axpu_cdev);
Same for that, just picking 6 will not work, sorry.
Yes, that was my original question. How can I get my irq number (I know it's hwirq 47) and I peeked into kernel that irq 6 was assigned for the irq_desc. So I changed my driver to request irq 6 for my device and I found at least it works for now, all the register access and interrupts. I know this is not the solution and I'm curious how I should get the irq number of io virtual address in this situation.
Perhaps take a look at the book, Linux Device Drivers, 3rd edition. It's free online and should help you out a lot.
printk("request_irq returned %d\n", ret); // -EINVAL printk(KERN_INFO "Device driver inserted ..done properly..\n"); return 0;
r_device : class_destroy(dev_class);
r_class : unregister_chrdev_region(dev,1); return -1;
One final comment, don't make up error values like this, use real ERROR codes.
thanks,
greg k-h
Yes, I've read the book sometimes (not the whole part) but if I read it now, I'll be able to more understand it. It's a bit outdated though. Why don't you update your book? :) Thank you again for the advices. Best regards, Chan Kim