The PCI device will exist whether or not the module was loaded; so you can just iterate over /sys/bus/pci/devices/* (* expands to the PCI bus IDs) and check the attributes in each directory; e. g. you probably want to pick out the ones with class == 0x030000 (graphics card), and perhaps vendor == 10DE (nvidia).
If you want to do that via an udev rule: I'm not entirely sure which kinds of events you get when the nvidia driver gets loaded. You can unload it, run
udevadm monitor -e --udev
then load it, and see what kind of events you get. For sure you'll see an "add" event for SUBSYSTEM=="module", DEVPATH=="*/nvidia", but either on boot or when loading the module you should also see an "add" or "change" event for the graphics card itself.
This is an initial sketch of a rule which selects a PCI card whose driver is nvidia:
(using "nvidia*" here in case the modules might be called something like nvidia_123). You can use udev properties like $env{PCI_ID} and also attributes from sysfs like the above, with e. g. $attr{vendor}. See man udev(7) for other macros you can use in RUN clauses.
Then you don't need the "remove" rule any more -- if /sys/modules/nvidia does not exist but your stamp in /run does exist, you know that it was once loaded but then removed.
The PCI device will exist whether or not the module was loaded; so you can just iterate over /sys/bus/ pci/devices/ * (* expands to the PCI bus IDs) and check the attributes in each directory; e. g. you probably want to pick out the ones with class == 0x030000 (graphics card), and perhaps vendor == 10DE (nvidia).
If you want to do that via an udev rule: I'm not entirely sure which kinds of events you get when the nvidia driver gets loaded. You can unload it, run
udevadm monitor -e --udev
then load it, and see what kind of events you get. For sure you'll see an "add" event for SUBSYSTEM= ="module" , DEVPATH= ="*/nvidia" , but either on boot or when loading the module you should also see an "add" or "change" event for the graphics card itself.
This is an initial sketch of a rule which selects a PCI card whose driver is nvidia:
ACTION= ="add|change" , SUBSYSTEM=="pci", DRIVER=="nvidia*", RUN+= "touch /run/nvidia- loaded- for-pci- id-$env{ PCI_ID} "
(using "nvidia*" here in case the modules might be called something like nvidia_123). You can use udev properties like $env{PCI_ID} and also attributes from sysfs like the above, with e. g. $attr{vendor}. See man udev(7) for other macros you can use in RUN clauses.
Then you don't need the "remove" rule any more -- if /sys/modules/nvidia does not exist but your stamp in /run does exist, you know that it was once loaded but then removed.