lspci shpchp and /sys vs /lib/modules questions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(Apologies to "mj" for duplicate send, the mailing list subscription was finally sorted out.)

The attached perl script tries to use lspci -n and the information in /sys/devices and /lib/modules/$kernel/modules.alias to describe the PCI devices on the system. I'm trying to make it tease out what drivers are built in (from /sys/devices) and which are loaded as modules (from /lib/modules). While overall this resembles the output of "lspci -k" there are a few differences I cannot explain yet.

On an old IBM server the outputs are:

lspci -k
00:01.0 PCI bridge: Broadcom BCM5785 [HT1000] PCI/PCI-X Bridge
        Kernel modules: shpchp
00:02.0 Host bridge: Broadcom BCM5785 [HT1000] Legacy South Bridge
        Subsystem: IBM BCM5785 [HT1000] Legacy South Bridge
        Kernel driver in use: piix4_smbus
        Kernel modules: i2c_piix4
00:02.1 IDE interface: Broadcom BCM5785 [HT1000] IDE
        Subsystem: IBM BCM5785 [HT1000] IDE
        Kernel driver in use: pata_serverworks
        Kernel modules: pata_serverworks, pata_acpi
00:02.2 ISA bridge: Broadcom BCM5785 [HT1000] LPC
        Subsystem: IBM BCM5785 [HT1000] LPC
00:03.0 USB controller: Broadcom BCM5785 [HT1000] USB (rev 01)
        Subsystem: IBM BCM5785 [HT1000] USB
        Kernel driver in use: ohci-pci
00:03.1 USB controller: Broadcom BCM5785 [HT1000] USB (rev 01)
        Subsystem: IBM BCM5785 [HT1000] USB
        Kernel driver in use: ohci-pci
00:03.2 USB controller: Broadcom BCM5785 [HT1000] USB (rev 01)
        Subsystem: IBM BCM5785 [HT1000] USB
        Kernel driver in use: ehci-pci
00:05.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] ES1000 (rev 02)
        Subsystem: IBM ES1000
        Kernel driver in use: radeon
        Kernel modules: radeonfb, radeon
00:06.0 PCI bridge: Broadcom HT2100 PCI-Express Bridge (rev a2)
        Kernel driver in use: pcieport
        Kernel modules: shpchp
00:07.0 PCI bridge: Broadcom HT2100 PCI-Express Bridge (rev a2)
        Kernel driver in use: pcieport
        Kernel modules: shpchp
00:08.0 PCI bridge: Broadcom HT2100 PCI-Express Bridge (rev a2)
        Kernel driver in use: pcieport
        Kernel modules: shpchp
00:09.0 PCI bridge: Broadcom HT2100 PCI-Express Bridge (rev a2)
        Kernel driver in use: pcieport
        Kernel modules: shpchp
00:0a.0 PCI bridge: Broadcom HT2100 PCI-Express Bridge (rev a2)
        Kernel driver in use: pcieport
        Kernel modules: shpchp
00:18.0 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration 00:18.1 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Address Map 00:18.2 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] DRAM Controller 00:18.3 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
        Kernel driver in use: k8temp
        Kernel modules: k8temp
00:19.0 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration 00:19.1 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Address Map 00:19.2 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] DRAM Controller 00:19.3 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
        Kernel driver in use: k8temp
        Kernel modules: k8temp
01:0d.0 PCI bridge: Broadcom BCM5785 [HT1000] PCI/PCI-X Bridge (rev c0)
        Kernel modules: shpchp
01:0e.0 RAID bus controller: Broadcom BCM5785 [HT1000] SATA (Native SATA Mode)
        Subsystem: IBM BCM5785 [HT1000] SATA (Native SATA Mode)
        Kernel driver in use: sata_svw
        Kernel modules: sata_svw
02:01.0 Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5704 Gigabit Ethernet (rev 10)
        Subsystem: IBM NetXtreme BCM5704 Gigabit Ethernet
        Kernel driver in use: tg3
        Kernel modules: tg3
02:01.1 Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5704 Gigabit Ethernet (rev 10)
        Subsystem: IBM NetXtreme BCM5704 Gigabit Ethernet
        Kernel driver in use: tg3
        Kernel modules: tg3
03:00.0 Mass storage controller: Silicon Image, Inc. SiI 3132 Serial ATA Raid II Controller (rev 01) Subsystem: Silicon Image, Inc. SiI 3132 Serial ATA Raid II Controller
        Kernel driver in use: sata_sil24
        Kernel modules: sata_sil24
06:00.0 Ethernet controller: Intel Corporation 82572EI Gigabit Ethernet Controller (Copper) (rev 06)
        Subsystem: Intel Corporation PRO/1000 PT Desktop Adapter
        Kernel driver in use: e1000e
        Kernel modules: e1000e
root@keyserver3:/tmp# lspci -k | head
00:01.0 PCI bridge: Broadcom BCM5785 [HT1000] PCI/PCI-X Bridge
        Kernel modules: shpchp
00:02.0 Host bridge: Broadcom BCM5785 [HT1000] Legacy South Bridge
        Subsystem: IBM BCM5785 [HT1000] Legacy South Bridge
        Kernel driver in use: piix4_smbus
        Kernel modules: i2c_piix4
00:02.1 IDE interface: Broadcom BCM5785 [HT1000] IDE
        Subsystem: IBM BCM5785 [HT1000] IDE
        Kernel driver in use: pata_serverworks
        Kernel modules: pata_serverworks, pata_acpi

vs.

 ./map_hardware_to_drivers.pl /tmp/pci.ids
Checking this machine for drivers
Getting Device ID list from https://pci-ids.ucw.cz/v2.2/pci.ids
Getting PCI ID to builtin mappings from /sys/bus/pci/drivers
Getting PCI ID to kernel module name mappingsChecking pci and device IDs from lspci -n
pci_id  dev_id    driver description
00:01.0 1166:0036 <none> "BCM5785 [HT1000] PCI/PCI-X Bridge"
00:02.0 1166:0205 i2c_piix4(module)/piix4_smbus(builtin) "BCM5785 [HT1000] Legacy South Bridge" 00:02.1 1166:0214 pata_serverworks(module)/pata_serverworks(builtin) "BCM5785 [HT1000] IDE"
00:02.2 1166:0234 <none> "BCM5785 [HT1000] LPC"
00:03.0 1166:0223 ohci-pci(builtin) "BCM5785 [HT1000] USB"
00:03.1 1166:0223 ohci-pci(builtin) "BCM5785 [HT1000] USB"
00:03.2 1166:0223 ehci-pci(builtin) "BCM5785 [HT1000] USB"
00:05.0 1002:515E radeonfb(module)/radeon(builtin) "ES1000"
00:06.0 1166:0140 pcieport(builtin) "HT2100 PCI-Express Bridge"
00:07.0 1166:0142 pcieport(builtin) "HT2100 PCI-Express Bridge"
00:08.0 1166:0144 pcieport(builtin) "HT2100 PCI-Express Bridge"
00:09.0 1166:0142 pcieport(builtin) "HT2100 PCI-Express Bridge"
00:0a.0 1166:0144 <none> "HT2100 PCI-Express Bridge"
00:18.0 1022:1100 <none> "K8 [Athlon64/Opteron] HyperTransport Technology Configuration"
00:18.1 1022:1101 <none> "K8 [Athlon64/Opteron] Address Map"
00:18.2 1022:1102 <none> "K8 [Athlon64/Opteron] DRAM Controller"
00:18.3 1022:1103 k8temp(module)/k8temp(builtin) "K8 [Athlon64/Opteron] Miscellaneous Control" 00:19.0 1022:1100 <none> "K8 [Athlon64/Opteron] HyperTransport Technology Configuration"
00:19.1 1022:1101 <none> "K8 [Athlon64/Opteron] Address Map"
00:19.2 1022:1102 <none> "K8 [Athlon64/Opteron] DRAM Controller"
00:19.3 1022:1103 k8temp(module)/k8temp(builtin) "K8 [Athlon64/Opteron] Miscellaneous Control"
01:0d.0 1166:0104 <none> "BCM5785 [HT1000] PCI/PCI-X Bridge"
01:0e.0 1166:024A sata_svw(module) "BCM5785 [HT1000] SATA (Native SATA Mode)" 02:01.0 14E4:1648 tg3(module)/tg3(builtin) "NetXtreme BCM5704 Gigabit Ethernet" 02:01.1 14E4:1648 tg3(module)/tg3(builtin) "NetXtreme BCM5704 Gigabit Ethernet" 03:00.0 1095:3132 sata_sil24(module)/sata_sil24(builtin) "SiI 3132 Serial ATA Raid II Controller" 06:00.0 8086:10B9 e1000e(module)/e1000e(builtin) "82572EI Gigabit Ethernet Controller (Copper)"
Done


Things I do not understand:

1. Devices 00:01.0 and 01:0d.0 show "Kernel modules: shpchp" in "lspci -k".
Where is "lspci -k" getting that information?
"ls /sys/module/shpch" does not indicate any links to those devices, nor
do those devices have any links to that module/driver. The others devices do link to their
drivers (and vice versa), for instance:

ls -al /sys/devices/pci0000:00/0000:00:02.1 | grep drivers
lrwxrwxrwx 1 root root 0 Mar 16 13:47 driver -> ../../../bus/pci/drivers/pata_serverworks

ls -al /sys/bus/pci/drivers/pata_serverworks | grep devices
lrwxrwxrwx 1 root root 0 Mar 16 13:48 0000:00:02.1 -> ../../../../devices/pci0000:00/0000:00:02.1

2. I describe the /sys/module heirarchy as "builtin", assuming that all the drivers in it are compiled into the running kernel. Is that actually true or will modules from /lib/modules/<kernel> show up in there too when they are loaded? If the latter is the case, how does one determine what is actually built into the kernel and what was added later?

3. lsmod shows which modules are loaded. Is there anything similar to show which builtin kernel drivers are being used? Or is deterimining which driver is in use an either/or sort of thing. For instance, for 06:00.0 the driver is e1000e for both builtin and module, and lsmod shows e1000e, so that is the module and not the builtin in use. If lsmod did not show it then it would be the builtin. That seems to be the case for these two:

  00:03.1 1166:0223 ohci-pci(builtin) "BCM5785 [HT1000] USB"
  00:03.2 1166:0223 ehci-pci(builtin) "BCM5785 [HT1000] USB"

Thank you,

David Mathog
mathog@xxxxxxxxxxx
Manager, Sequence Analysis Facility, Biology Division, Caltech
#!/usr/bin/perl
#Name:    map_hardware_to_drivers.pl
#version: 1.0.0
#Date:    2020-03-12
#Author:  David Mathog
#
#  Map the pci hardware list to drivers for the running kernel
#
#  assumes wget, lspci, and access to the internet are available
#  If access is not available specify one parameter to the already downloaded
#  PCI IDs file.
#
#
use strict;
use warnings;
my $IDLIST="https://pci-ids.ucw.cz/v2.2/pci.ids";;
my $real_filename="/tmp/pci.ids";
my $kernel=`uname -r`;
chomp $kernel;
my $MODALIAS="/lib/modules/$kernel/modules.alias";
my %dev_hash_longname;
my %dev_hash_module;
my %pci_hash_builtin;
my $count=0;
my $vendor="";
my $device="";
my $long_name="";
my $module_name="";
my $pci_id;
my $dev_id;
my $ignore;

my $num_args = $#ARGV;
if ($num_args != 0) {
    print 
     "Usage: map_hardware_to_drivers.pl PciIDsFile\n\n",
     "If internet access is available let PciIDsFile = \"-\" and it will be downloaded\n",
     "automatically.  Otherwise on some machine do:\n\n",
     "   wget -O PciIDsFile $IDLIST\n\n",
     "Then copy that file by some means to the target and specify\n",
     "the file name on the command line.\n";
    exit;
}
my $filename=$ARGV[0];



if($filename eq '-'){
   my $messages = `wget -q -O $real_filename $IDLIST 2>/dev/null`;
   if($messages){
      print
        "Some problem running:\n\n",
        "  wget -q -O $real_filename 2>/dev/null\n\n",
	"returned:\n",
	"$messages\n";
      exit;
   }
}
else {
   $real_filename = $filename;
}

#######################
open(FH, $real_filename) or die "could not open file $real_filename";

print "Checking this machine for drivers\n";
print "Getting Device ID list from $IDLIST\n";
# Syntax in this file:
#   #comment line
#   <blank lines>
#   vendor  vendor_name
#	device  device_name				<-- single tab
#		subvendor subdevice  subsystem_name	<-- two tabs
#   Only the vendor and device lines are retained
#(This will obtain all PCI ID -> long name mappings even if the current kernel does
#not have the information.)
while (my $line = <FH>){
    chomp $line;
    if(! $line){ next; }
    if(substr($line,0,1) eq "#"){ next; }
    if(substr($line,0,2) eq "\t\t"){ next; }
    if(substr($line,0,1) eq "\t"){ #device line
       $device = substr($line,1,4);
       $long_name = substr($line,7);
       $dev_id = $vendor . ":" . uc $device;
       $dev_hash_longname{$dev_id} = $long_name;
    }
    else { #vendor line
       $vendor = uc substr($line,0,4);
    }
}
close(FH);
#       my ($dev_type, $dev_id, $dev_driver) = split(/\s+/,$line);

#print "Getting pci IDs and long names from lspci\n";
#foreach my $line (`lspci`){
#    chomp $line;
#    my $starts = index($line," ");
#    my $pci_id = uc substr($line,0,$starts);
#    my $ln = substr($line,$starts+1);
#    $dev_hash_longname{$pci_id}=$ln;
#}

#######################
# get all the PCI ID to builtin mappings.
print "Getting PCI ID to builtin mappings from /sys/bus/pci/drivers\n";
foreach my $line (`find /sys/bus/pci/drivers`){
    chomp $line;
    my $starts = index($line,"/0000:");
    if($starts != -1){
       my $pci_id = uc substr($line,$starts + 6);
       my $delim = rindex(substr($line,0,$starts-1),"/");
       my $driver= substr($line,$delim+1,$starts - $delim -1);
#       print "pci_id >$pci_id< driver >$driver<\n";
       $pci_hash_builtin{$pci_id}=$driver . "(builtin)";
    }
}

#######################
# get all the PCI ID to module name mappings.  Ignore subvendor and subdevice information.
# This uses the "alias pci:" lines which have the syntax:
#   alias pci:vVENDORdDEVICEsvSUBVENDORsdSUBDEVICEscIGNOREiIGNORE module_name
# extract the VENDOR and DEVICE files to construct a PCI ID like 1234:ABCD
# Use that to store the module_name value in a hash.
#

open(FH, $MODALIAS) or die "could not open file $MODALIAS";
print "Getting PCI ID to kernel module name mappings";

my $next_delim;
while (my $line = <FH>){
    chomp $line;
    if(substr($line,0,10) eq 'alias pci:'){
#       print "line: $line\n";
       if(substr($line,11,1) eq "*"){ next; }
       $next_delim=index($line,"d",11);
       if($next_delim == -1){ die "File $MODALIAS has pci: line with unexpected syntax: $line"; }
       $vendor = substr($line,15,4);
       $next_delim=index($line,"sv",20);
       if($next_delim == -1){ die("File $MODALIAS has pci: line with unexpected syntax: $line"); }
       $device = substr($line,24,4);
       $dev_id = $vendor . ":" . $device;
       $next_delim=index($line," ",28);
       if($next_delim == -1){ die "File $MODALIAS has pci: line with unexpected syntax: $line"; }
       $module_name = substr($line,$next_delim + 1);
       if(defined($dev_hash_module{$dev_id})){ next; } #subvendor/subdevice lines
       $dev_hash_module{$dev_id} = $module_name . "(module)";
       $count++;
#       print "  parsed $dev_id $module_name\n";
    }
}
close(FH);

print "Checking pci and device IDs from lspci -n\n";
print "pci_id  dev_id    driver description\n";
foreach my $line (`lspci -n`){
    chomp $line;
    ($pci_id, $ignore, $dev_id)= split /\s/,$line;
    $dev_id = uc $dev_id;
    my $description = (defined($dev_hash_longname{$dev_id}) ? $dev_hash_longname{$dev_id} : "unknown");
    my $module = (defined($dev_hash_module{$dev_id}) ? $dev_hash_module{$dev_id} : "");
    my $builtin = (defined($pci_hash_builtin{$pci_id}) ? $pci_hash_builtin{$pci_id} : "");
    if(!$module){
       if($builtin){
          $module = $builtin;
       }
       else {
          $module = "<none>";
       }
    }
    else {
       if($builtin){
          $module .= "/" . $builtin;
       }
    }
    print "$pci_id $dev_id $module \"$description\"\n";
}
if($filename eq "-"){
   unlink($real_filename);
}
print "Done\n";

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux