In some cases, i can be needed to reset a PCI device without restarting the system. This guide describe how to reset a PCI device from command line.

This howto is tested on:

  • Ubuntu 15.10 Wily Werewolf
  • Debian 10.0 Buster

Settings

Provide the search text identifying the PCI device in “lspci” command results (in this example, for USB controllers):

pciSearchString="USB controller"

Reset of the PCI devices

Detect if sudo is available (“command” is used if not):

cmdProxy='command'
command type -f 'sudo' &>'/dev/null' && cmdProxy='sudo'

Fetch the complete PCI ids of the chosen devices:

pciIds="$(command lspci \
  | command egrep -i "${pciSearchString}" \
  | command cut -c -7)"

Detect the kernel modules used for the chosen PCI devices:

declare -a pciInfos=()
for pciId in ${pciIds}; do
  pciInfos+=( "$(command lspci -v -s "${pciId}" \
    | command grep 'Kernel driver in use' \
    | command sed -e "s/^.*: /${pciId}|/")" )
done

Reset the PCI devices by unbinding them from and then rebinding them to their kernel modules:

for pciInfo in "${pciInfos[@]}"; do
  pciId="${pciInfo%|*}"
  longPciId="0000:${pciId}"
  driver="${pciInfo#*|}"
  if [[ -e "/sys/bus/pci/drivers/${driver}/${longPciId}" ]]; then
    echo "Unbinding ${pciId} from ${driver}"
    echo " echo '${longPciId}' > '/sys/bus/pci/drivers/${driver}/unbind'"
    echo "${longPciId}" | ${cmdProxy} tee "/sys/bus/pci/drivers/${driver}/unbind" > '/dev/null'
  fi
  if [[ -n "${pciId}" && -e "/sys/bus/pci/drivers/${driver}/bind" ]]; then
    echo "Binding ${pciId} to ${driver}"
    echo " echo '${longPciId}' > '/sys/bus/pci/drivers/${driver}/bind'"
    echo "${longPciId}" | ${cmdProxy} tee "/sys/bus/pci/drivers/${driver}/bind" > '/dev/null'
  fi 
done

Check that the PCI devices has been reset with dmesg:

${cmdProxy} dmesg

Thanks

Categories: Setup

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.