udev and a new device
(I'm running gentoo, so maybe that's the source of my problem. The folks over on forums.gentoo.org don't seem to be able to answer this question.)
udev is supposed to be the be-all end-all for /dev management. If that is the case then there must be a way to have udev build /dev entries automatically. Not just for some things, but for all things. Sure, it's my responsibility to set up the rules if I add something non-standard, and that's fine. But the mechanism to do so has to be in place. That MUST be part of udev, otherwise udev is not an acceptable solution for managing /dev. I have a PCI I/O board in my system. The device driver, a loadable module, works perfectly but I have to use a MAKEDEV script to build the /dev entries. When I reboot the system these nodes disappear so I have to (manually) create them again. What *should* happen is that when the device driver is loaded (on boot, or manually as I keep reloading after tweaking values) udev should recognize this and create or destroy the relevant entries. Maybe udev only needs to call the MAKEDEV script, but whatever happens should do so automatically. The module is called s626.ko, and the devices built are /dev/s626a[0-3]. If I had a second board in the system the devices would be called /dev/s626b[0-3]. Right now what happens is -- nothing. Oh, sure, an entry appears and disappears in /sys as I load and unload the module, but there is no activity beyond that. So what event happens to make udev aware that new /dev nodes must be created? How can I verify that udev is picking up on this event? Someone pointed out that udev has the option to tar up the /dev directory on shutdown for restoration on boot later, so I could create the entries once then activate the 'save' feature. That is not a solution. A cop-out, a hack, but certainly not a solution. Because of the dynamic nature of the modern /dev structure, device major numbers can change, so the "static" (perhaps "stale" is a better word) entries in the tar file run a great risk of being wrong on subsequent boots. I've gone through all the documentation I could find. Some of the better stuff (still does not help me here, though): - udev manpage - "Writing udev rules" but Daniel Drake. This is a pretty good document, but does not cover my situation. - "UDEV Primer" on Decibels Linux. More good info, but doesn't cover my situation. Any suggestions on how to proceed or where to start digging? |
few questions
what does dmesg say and lspci is it a standard kernel module or did you have to compile it? is the kernel module being inserted at boot? |
Answers (in a different order than asked):
This is not a standard kernel module, we compile it separately. It's part of the SDK we get with the product. On one system I load it at boot. On another system I load it when I need to work with that card (used to control and monitor an external device). Here's the output. Actually, there are 3 non-standard cards in this system. I have the same issue with udev for all of them. I figured I'll get help on the easy one first before I tackle the rest. That said, I can not tell you which entries correspond to the s626 card I mention. But here you go: ------ dmesg: ------ When I load the module: S626: s626 installed - device major number = 146 S626_init_one(): Detected S626 Card - Address=0xfab21000 io_size=0x200 irq=22 Slot=0000:06:01.0 S626_init_one():Card S626 #0 added. Board[0].base=0xf8980000 When I remove the module: Card S626 #0 removed. -------------------- udevmonitor --kernel -------------------- When I load the module: UEVENT[1191518376.602780] add /module/s626 (module) UEVENT[1191518376.603479] add /bus/pci/drivers/S626 (drivers) When I remove the module: UEVENT[1191518378.324324] remove /bus/pci/drivers/S626 (drivers) UEVENT[1191518378.324422] remove /module/s626 (module) ------ lspci: ------ 00:00.0 Host bridge: Intel Corporation 915G/P/GV/GL/PL/910GL Express Memory Controller Hub 00:01.0 PCI bridge: Intel Corporation 915G/P/GV/GL/PL/910GL Express PCI Express Root Port 00:1b.0 Audio device: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (rev 03) 00:1c.0 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (rev 03) 00:1c.1 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (rev 03) 00:1c.2 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (rev 03) 00:1c.3 PCI bridge: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (rev 03) 00:1d.0 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (rev 03) 00:1d.1 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (rev 03) 00:1d.2 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (rev 03) 00:1d.3 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (rev 03) 00:1d.7 USB Controller: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (rev 03) 00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev d3) 00:1f.0 ISA bridge: Intel Corporation 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (rev 03) 00:1f.1 IDE interface: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (rev 03) 00:1f.2 IDE interface: Intel Corporation 82801FB/FW (ICH6/ICH6W) SATA Controller (rev 03) 00:1f.3 SMBus: Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (rev 03) 01:00.0 VGA compatible controller: nVidia Corporation G70 [GeForce 7800 GT] (rev a1) 06:01.0 Multimedia controller: Philips Semiconductors SAA7146 (rev 01) 06:02.0 Co-processor: Unknown device 1892:5747 06:03.0 Network controller: Unknown device 001c:0001 (rev 02) 06:08.0 Ethernet controller: Intel Corporation 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller (rev 01) |
i would try adding it to /etc/modprobe.conf so that it will load on boot. I think it will play a little better with udev if it is loaded at boot because the modules are loaded before udev scans for all devices.
|
Quote:
udev is designed to work with things like USB device insertion and removal, and these certainly happen after the computer boots. So how is it that udev works with these devices but not other devices? To my simple mental model it's the same thing: The kernel says "Hey! New Hardware!" or "Hey! That hardware went away!". These are triggered by (or in conjunction with) changes to /sys, which happens when a USB drive is inserted/removed or when a module is loaded/unloaded, as evidenced by the udevmonitor snippet included in my previous post. Can someone explain the difference? Again, thanks for your explanations and suggestions. --Jim |
udev won't install modules
|
Quote:
|
It seems to me that your driver was written without an actual device registration occurring (this is common for “old” drivers). For example, if you use something low-level like register_chrdev() instead of something higer-level like misc_register(), you will get reserved major and minor numbers, yet no uevent for device creation will be sent. In your case, if such a uevent was sent, it udevmonitor would have told you with
Code:
add /class/foo/bar (foo) Code:
KERNEL=="hd*[!0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/ata-$env{ID_MODEL}_$env{ID_SERIAL}" Code:
ACTION=="add", DEVPATH=="/bus/pci/drivers/S626", RUN+="mk_S626.sh" P.S., if you want to see detailed, matchable variables in udevmonitor, try using Code:
udevmonitor -ek |
Quote:
|
Quote:
--Jim |
I neglected to mention that the script will inherit all environment variables from udev (including ACTION and DEVPATH). If you want to pass your own custom environment variables, you can use ENV{foo}=bar. Then, in your script, you can access $foo as you normally would. You can use the ACTION environment variable to write one script with two branches, checking for add or remove as the value of $ACTION.
P.S., a caveat about variable assignment syntax: the udev rules use syntax similar to C, where == indicates testing for equality, and = indicates assignment. When writing the matching part of the rule, use the first form (e.g., ACTION=="add", DEVPATH=="/bus/pci/drivers/S626"). When assigning a variable for a successful match, use the second form (e.g., RUN="mk_S626.sh"). P.P.S., remember that the script will be run with root permissions. Approach it security-wise the same way you approach writing init-scripts. |
Osor: Your description of what was not happening with the old drivers was a huge help. The ACTION and DEVPATH matches were exactly what I needed.
I created a script to create or destroy the nodes and symlinks, based on the manufacturer's MAKEDEV script, but much cleaner. I load a module: the nodes appear. I rmmod the device, the nodes disappear. Yee-ha. This thread was triply useful because I have another device which has the same problem: the device driver is older and so udev integration required the same handling. That script works perfectly, too. So I'm 100% good for two of my boards. For my third board I'm about 95% there.... The script calculates the device minor numbers, creates the nodes, then changes the group and mode: Code:
... .... mknod: '/dev/pcan8': File exists .... chgrp: cannot access '/dev/pcan25': No such file or directory .... chmod: cannot access '/dev/pcan4': No such file or directory Now, as far as I can tell the script runs once and only once when the module is loaded. All of the nodes are always created, they just end up in various combinations of group and ownership. It almost seems there is some sort of race condition going on here, but I don't see how that can be. Any thoughts on what might be going on? |
Quote:
I then tried several unloads and loads of the module. No randomness -- groups fine, modes fine. So I guess there is no problem after all. Thanks, everyone! --Jim |
All times are GMT -5. The time now is 07:51 PM. |