Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
en:pcie:hot-reset-linux [2019/04/16 23:00] alex |
en:pcie:hot-reset-linux [2019/04/16 23:02] alex |
||
---|---|---|---|
Line 11: | Line 11: | ||
A 'function-level reset' (FLR) is a reset that affects only a single function of a PCI express device. It must not reset the entire PCIe device. Implementing function-level resets is not required by the PCIe specification. A function-level reset is initiated by setting the initiate function-level reset bit in the function's device control register in the PCI express capability structure in the PCI configuration space. | A 'function-level reset' (FLR) is a reset that affects only a single function of a PCI express device. It must not reset the entire PCIe device. Implementing function-level resets is not required by the PCIe specification. A function-level reset is initiated by setting the initiate function-level reset bit in the function's device control register in the PCI express capability structure in the PCI configuration space. | ||
- | Linux exposes the function-level reset functionality in the form of /sys/bus/pci/devices/$dev/reset. Writing a 1 to this file will initiate a function-level reset on the corresponding function. Note that this only affects that specific function of the device, not the whole device, and devices are not required to implement function-level resets as per the PCIe specification. | + | Linux exposes the function-level reset functionality in the form of ''/sys/bus/pci/devices/$dev/reset''. Writing a 1 to this file will initiate a function-level reset on the corresponding function. Note that this only affects that specific function of the device, not the whole device, and devices are not required to implement function-level resets as per the PCIe specification. |
I am not aware of any 'nice' method for triggering a hot reset (there is no sysfs entry for that). However, it is possible to use setpci to do so with the following script: | I am not aware of any 'nice' method for triggering a hot reset (there is no sysfs entry for that). However, it is possible to use setpci to do so with the following script: | ||
+ | <code sh> | ||
+ | #!/bin/bash | ||
- | <code sh> | + | dev=$1 |
+ | |||
+ | if [ -z "$dev" ]; then | ||
+ | echo "Error: no device specified" | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | if [ ! -e "/sys/bus/pci/devices/$dev" ]; then | ||
+ | dev="0000:$dev" | ||
+ | fi | ||
+ | |||
+ | if [ ! -e "/sys/bus/pci/devices/$dev" ]; then | ||
+ | echo "Error: device $dev not found" | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev"))) | ||
+ | |||
+ | if [ ! -e "/sys/bus/pci/devices/$port" ]; then | ||
+ | echo "Error: device $port not found" | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | echo "Removing $dev..." | ||
+ | |||
+ | echo 1 > "/sys/bus/pci/devices/$dev/remove" | ||
+ | |||
+ | echo "Performing hot reset of port $port..." | ||
+ | |||
+ | bc=$(setpci -s $port BRIDGE_CONTROL) | ||
+ | |||
+ | echo "Bridge control:" $bc | ||
+ | |||
+ | setpci -s $port BRIDGE_CONTROL=$(printf "%04x" $(("0x$bc" | 0x40))) | ||
+ | sleep 0.01 | ||
+ | setpci -s $port BRIDGE_CONTROL=$bc | ||
+ | sleep 0.5 | ||
+ | echo "Rescanning bus..." | ||
+ | echo 1 > "/sys/bus/pci/devices/$port/rescan" | ||
</code> | </code> |