6

I'm working on a project where I have a management system that exports PCIe hardware devices to other systems via PCI Express. I have a working management kernel module but need to find a way to ensure that a device I export doesn't have a driver already loaded for it on the management system. Without that, the device will end up with conflicts since the same driver will be accessing it from 2 different systems & obviously cause problems.

For example, assume I have a dual-port Intel 100MBps NIC device installed on the Manager which will show up 2 PCIe Endpoints in the system (eg Fn 0 & 1). The Intel module e1000 will be loaded for both devices. If I want to export port 2 of that device to another system, I would like to "detach" it from the e1000 module.

Does anyone know a clean way of doing this without hacking the kernel or tweaking the e1000's driver's probe function? I can't simply do an rmmod because that will remove the module all-together for both NIC devices. I would like the NIC I'm not exporting to remain functional in the Management system with the e1000 driver still loaded for it.

Essentially, rmmod does this but will remove the driver for all devices probed for & owned by the driver. Any way to tell Linux just "unload module for only this specific device"? On Windows, I guess this would be the equivalent of right-clicking on a device in Device Manager & select "Disable".

tshepang
  • 12,111
  • 21
  • 91
  • 136
user3015665
  • 61
  • 1
  • 1
  • 2

4 Answers4

8

You can disable driver for your device by writting following method:

  • Use sudo -i or before any command write sudo to operate as root user.And follow below procedure:
  • Goto /sys/bus/pci/<driver_name>/ folder.
  • Give command echo -n 0000:03:00.1 > unbind
  • Where 0000:03:00.1 is device you want to detech your driver.
  • Read this link for getting idea about sysfs for pci bus.
RDX
  • 409
  • 6
  • 22
2

The mechanism responsible for device/driver pairing in Linux driver model is called "bus" (usually controlled through entries in /sys/bus). The problem is, the particular bus driver your device is attached to must support this sort of action (and it is far from trivial supporting this functionality in general case).

Specifically for PCI, if you've got "pci hotplug" enabled, you will be able to kick devices off pci bus by writing numbers to corresponding "hotplug" entries in /sys/bus/pci (you can also reconnect them back by triggering the bus rescan). The problems will start later, as you will have to somehow convince the Linux device subsystem to prefer your driver over the one already registered for the device id in question.

Normally registered drivers are added to some sort of list and then tried out one by one to see if either of them is listing the new or re-enabled device in their "*_device_id" tables. If PCI subsystem prefers to try drivers in "first registered, first tried" order you will have to hack it to achieve your goal.

oakad
  • 6,945
  • 1
  • 22
  • 31
1

To unbind a PCI driver from a device, use the unbind file of the driver in sysfs.

From Documentation/ABI/testing/sysfs-bus-pci:

/sys/bus/pci/drivers/.../unbind
Description:
        Writing a device location to this file will cause the
        driver to attempt to unbind from the device found at
        this location.  This may be useful when overriding default
        bindings.  The format for the location is: DDDD:BB:DD.F.
        That is Domain:Bus:Device.Function and is the same as
        found in /sys/bus/pci/devices/. For example:
        # echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/unbind
CL.
  • 173,858
  • 17
  • 217
  • 259
0

you can disable a particular pci device by resetting enable value for the corresponding device

Eg:

echo 0 > /sys/bus/pci/devices/0000:00:1a.2/enable
Sun
  • 1,505
  • 17
  • 25