I'm trying a driver for a custom hardware component, the source code can be found here:
https://github.com/godspeed1989/zedboard/blob/master/led_drv/driver/myled.c
the problem is that when i do:
insmod myled.ko
nothing is shown in the console or in the dmesg log. I'm reading Linux Device Driver 3 and on it is written that you always must do:
module_init(init_function);
module_exit(exit_function);
in the source code there are none of them, instead there is:
module_platform_driver(myled_driver);
But when i load a module with this function nothing is print, instead if I use module_init and module_exit messages appear, what are the difference between this two kind of istructions?
"but why the latter statement doesn't work while the first it's ok? "
The first methond will register the driver to system and bus by module_platform_driver macro.
The latter statement will not register your driver to system and bus. To to this, you need register driver in the init_function() routine by calling platform_device_register().
Related
I am looking for wait_event_timeout[1] equivalent function in u-boot but could not find the same.
is there such fuction do exist in u-boot ?
[1] https://github.com/torvalds/linux/blob/master/include/linux/wait.h#L371
U-Boot runs with a single process and a single thread. Interrupts are not enabled for many platforms. So a function like wait_event_timeout() cannot be implemented.
Instead you will have to create a loop that constantly checks if the event has occurred and in the loop execute whatever it takes to let the event occur.
For example look at the efi_wait_for_event() function which in a loop calls efi_timer_check(). efi_timer_check() runs all registered timer based functions like checking the network interface for received packages.
I am writing a device driver in linux for PCIe endpoint implemented on Xilinx UltrascaleMPSoC FPGA part. I have implemented the remove function correctly. I connect my device using an adapter to my PC, turn on device, enable its Endpoint and then turn on PC and everything works correctly. However, when I try to unload the driver module using rmmod command, the process hangs.
I went through Linux documentation and for pci_disable_device() documentation, it says
Note we don't actually disable the device until all callers of pci_enable_device() have called pci_disable_device().
Does it mean, my driver has to wait untill every other pcie driver in linux calls pci_disable_device() and only then device gets disabled? I really doubt upon this :(
I tried using modprobe -r and also listed the module usage count using "lsmod". lsmod shows usage count as "0". But still I am not able to unload the module :( I also added print statements.
void remove(struct pci_dev pdev)
{
pci_unmap_single(pdev, privdata->dma_mem,
PAGE_SIZE * (1 << memorder),
PCI_DMA_FROMDEVICE);
printk(KERN_INFO"unmap_single() complete\n");
free_pages ((unsigned long) privdata->mem, memorder);
printk(KERN_INFO"free_pages() complete\n");
free_irq(pdev->irq, privdata);
printk(KERN_INFO"free_irq() complete\n");
pci_disable_msi(pdev);
printk(KERN_INFO"MSI disable complete\n");
pci_clear_master(pdev); /* Nobody seems to do this */
printk(KERN_INFO"clear_master() complete\n");
pci_iounmap(pdev, privdata->registers);
printk(KERN_INFO"iounmap() complete\n");
pci_disable_device(pdev);
printk(KERN_INFO"disable_device() complete\n");
pci_release_regions(pdev);
printk(KERN_INFO"release_regions() complete\n");
}
Expected: The device must get disabled. I can't conclude. When I do a dmesg in another terminal, I get prints till "disable_device() complete" and the terminal hangs.Also,I checked the files: /proc/iomem and /proc/interrupts-> when I unload the module, corresponding entries of my device is removed in both of my files! I only complete the execution of pci_disable_device() and the process hangs.
Note: Only the rmmod process hangs and I cannot use the current terminal, but I can open another terminal, do all things.
Finally, when the do a restart, the system hangs again and everytime, I am doing force restart by holding power button for 10-15 seconds.
Check this reboot_hang
Why is the pci_release_regions() hanging my system even though lsmod shows my module usage count as "0".
Thanks in advance :)
Also, should I interchange pci_disable_device() and pci_release_regions() methods in above code? -> I tried this as well, but then I get prints till release_regions() complete but disable_device complete is not printed. And process hangs :(
Please help
Difficult to answer without more information on what you really use on your driver.
But, I will try to give you an answer.
Does it mean, my driver has to wait untill every other pcie driver in linux calls pci_disable_device() and only then device gets disabled?
No, this would make impractical and not very modular.
It seems you're freeing the DMA pages. How are you allocating them ? Are you using coherent allocation? Take a look here to see how to use properly the DMA.
For the remainder, can you try to move release regions before clear_master? Example :
pci_disable_msi(pdev);
ioummap(ADDRESS);
pci_release_regions(pdev);
pci_clear_master(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
For more information on how to write PCI Drivers, check the documentation here. It provides a lot of information.
# All,
Have got a requirement to replace a character driver ioctl function pointer. Would like to tap into the ioctl implementation of a character driver and replace that function pointer with mine(so that, we could intercept all calls getting into that character device, say X).
Have checked, include/linux/fs.h & fs/char_dev.c. Didn't find any pointers/hints for tapping in character driver IOCTL implementation.
Kernel version used : 4.9.35 (Any kernel version above 3.10 should be also fine).
Can someone point at any possible way if it exists ?
Any help is much appreciated.
I am trying to initiate a spi communication between an omap processor an sam4l one. I have configured spi protocol and omap is the master. Now what I see is the test data I am sending is correctly reaching on sam4l and I can see the isr is printing that data. Using more printf here and there in isr makes the operation happen and the respective operation happens, but if I remove all printfs I can't see any operation happening. What can be the cause of this anomaly? Is it a usual case of wrong frequency settings or something?
If code is needed I will post that too but its big.
Thanks
I think you are trying to print message in driver.
As printing message on console with slow down your driver, it may behave slowly and your driver work well.
Use pr_info() for debug and change setting to not come message on console by editing /proc/sys/kernel/printk to 4 4 1 7
-> It will store debug message in buffer.
-> Driver not slow down because of printing message on screen.
-> And you can see it by typing dmesg command later.
Then find orignal problem which may cause error.
If a routine works with printf "here and there" and not otherwise, almostcertainly the problem is that there are timing issues. As a trivial example, let's say you write to an SPI flash and then check its content. The flash memory write will take some times, so if you check immediately, the data would not be valid, but if you insert a printf call in between, it may have taken enough time that the read back is now valid.
I'm customising Linux for an ARM9 Atmel AT91SAM960 board.
In the device file Atmel named all the USART the same atmel_usart. Of course with id enumeration:
static struct platform_device at91sam9260_uart0_device = {
.name = "atmel_usart",
.id = 1,
.dev = { ...}
}
According to the Linux Device model, all these devices (5 UARTS on a SAM9260) would be bind to the driver named atmel_usart.
I don't want to set a TTYS driver on all UARTS which will be registerd. I have several own drivers which serve for different specialised purposes (LON, RS-485 etc.) I want the control which driver does serve a certain USART. So what could I do:
The Atmel device files are unsatisfiable and I can do it better. So I rename (patch) the devices in the device file. However, in case I want a TTYS driver on UART4 I would be in trouble.
I manipulate (patch) the device file,
so that I'm able the access the
structures platform_device. I could
change their names before I would
register them. But as far as I
understood the idea of the Linux Driver Model,
devices should be
registered early during boot-up but the binding to a driver follows .... later.
I could write a driver, which has an
alias name and which would be binded
to a specific bus_Id ->
atmel_usart.4. Can I really?
What solutions else exist. I want to touch a minimal set of Kernel files but I want all the freedom possible?
Addendum what freedom means to me: I can specify at runtime how the UARTS can be used
with the Atmel-Serial driver (ttyS)
with my own drivers
It means also, that changes to the kernel source are minimal.
I built my own line discipline drivers. You can build them as kernel modules and attach them to the UARTs at runtime. No changes to the Linux source are necessary.
Any funny timing or control stuff can be done through ioctl(). Specifically, I implemented a timing-sensitive RS-485 protocol in this way.
When I did this (Linux 2.6.17) there was no dynamic registration mechanism, so I overwrote the existing line disciplines. The Linux code is (was) pretty straightforward, and I was satisfied that this would be a safe thing to do.
Your problem is quite easily solved. The 5 UART devices are presently registered at kernel startup and their function is locked. This is now how it normally works for PCI or USB devices, right? So what you need to do is pull the device registration out of the startup code and register it dynamically. You can even register/unregister as needed.
at91_register_uart() is being called from your board file for every UART that needs registered. at91_add_device_serial() will then platform_device_register all those you what setup. One solution is to let at91_register_uart() be called for all 5 UARTS, but then remove the call to at91_add_device_serial() from your board. You can then make it an exported function that can be called by your loadable drivers. You can even add an argument to it (int) so that instead of looping on all UARTS, you can select which ones to register individually. You can also mirror this function by making one that unregisters the devices.
NOTE: I think you'll need to always leave one UART dedicated as your console, if you are using one that way. You could probably hide that in the exported function by only allowing index 0->3 as in input and then mapping 0->3 to 0-4, skipping the UART that you want to use for console.