Kernel Module Parameters

Working With Linux Kernel Modules

While studying for my lpic-1 exam I have been learning more about kernel modules. One thing that is useful is identifying and configuring the options associated with the kernel modules or the kernel parameters. In the process of inspecting the kernel modules I identified some parameters for a couple of modules that I wondered if it would be helpful to set. The modules I was looking at were are 'btusb' and 'iwlmvm'. These modules caught my attention because they are used on my wireless card on my desktop. They offer some power saving features because they are traditionally used on a laptop, but since the hardware is installed on my desktop I want to make sure these features are turned off. I did have an issue with my Bluetooth ear buds loosing connection after 20 or 30 minutes sometimes so I thought this could be part of the issue. WiFi I want to make sure is always working it's best and isn't switching in and out of a power saving mode which can cause issues.

Finding Kernel Module Parameters

To manipulate these parameters we need to figure out what they are. To do that we need to know what module is being used by the hardware. There are multiple ways to do this depending on how the hardware is connected to the system.

lspci

For the WiFi card, it is connected to the Peripheral Component Interconnect Express (PCIe) bus. It's a card that plugs into a PCIe slot and is exposed to the system. We can inspect components connected to this bus with the lspci command. Here is a sample of the output that includes information on the wireless card installed in the system.

02:00.0 USB controller: Fresco Logic FL1100 USB 3.0 Host Controller (rev 10)
03:00.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
04:00.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
04:01.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
04:02.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
04:04.0 PCI bridge: Intel Corporation DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
07:00.0 USB controller: Intel Corporation DSL6540 USB 3.1 Controller [Alpine Ridge]
09:00.0 Network controller: Intel Corporation Wi-Fi 6 AX200 (rev 1a)
0a:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM951/PM951 (rev 01)

We can see which hardware is installed and detected, it's address on the PCIe bus and a description of the hardware.
09:00.0 Network controller: Intel Corporation Wi-Fi 6 AX200 (rev 1a)
This is the WiFi card. Now we want to find out what module is being used with this card. lspci can give us this info pretty easily, it has a couple option flags we can use.
-s 9:0.0 will select the specific device in question
-k will specifically tell lspci we want to know the kernel module being used with the hardware

# lspci -s 9:0.0 -k
09:00.0 Network controller: Intel Corporation Wi-Fi 6 AX200 (rev 1a)
    Subsystem: Intel Corporation Wi-Fi 6 AX200
    Kernel driver in use: iwlwifi
    Kernel modules: iwlwifi

Great! We know the iwlwifi module is being used for our WiFi card. Now let's figure out what module is being used for our Bluetooth adapter.

lsusb

Our Bluetooth adapter was not listed with lspci, it's not connected to the system the same way. The adapter is a USB adapter, lsusb is very similar to lspci but give us a list of USB hardware connected to the system.

# lsusb
Bus 001 Device 005: ID 0451:2036 Texas Instruments, Inc. TUSB2036 Hub
Bus 001 Device 003: ID 1e7d:2e23 ROCCAT Kone XTD Optical Mouse
Bus 001 Device 006: ID 8087:0029 Intel Corp. AX200 Bluetooth
Bus 001 Device 004: ID 1e7d:3232 ROCCAT Ryos MK Pro Keyboard
Bus 001 Device 002: ID 04b4:6572 Cypress Semiconductor Corp. Unprogrammed CY7C65642 hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

This is a sample of the output from my system after running the command. We have a similar output, but we will use different flags to get the info we need. The USB devices have two different ways to reference them, the bus and device number or we can use the ID which is two parts [vendor]:[product]. We will need the bus and device number unfortunately lsusb doesn't have an "easy" way to give us just the module name we are after but it's still pretty easy to get.

# lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
        |__ Port 3: Dev 4, If 1, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 3: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 5: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 5: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 6: Dev 5, If 0, Class=Hub, Driver=hub/3p, 12M
        |__ Port 2: Dev 7, If 0, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 2: Dev 7, If 1, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 3: Dev 8, If 4, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 8, If 2, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 8, If 0, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 8, If 5, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 3: Dev 8, If 3, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 8, If 1, Class=Audio, Driver=snd-usb-audio, 12M
    |__ Port 14: Dev 6, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 14: Dev 6, If 1, Class=Wireless, Driver=btusb, 12M

Here we used the "tree" flag and we can see all the devices on Bus 01. We find Dev 6, our Bluetooth adapter and we can see the driver in use by it is btusb.

|__ Port 14: Dev 6, If 0, Class=Wireless, Driver=btusb, 12M
|__ Port 14: Dev 6, If 1, Class=Wireless, Driver=btusb, 12M

lsmod

Let's get some more info on the modules that our hardware is using.

# lsmod | grep 'iwlwifi'
iwlwifi               380928  1 iwlmvm
cfg80211              892928  3 iwlmvm,iwlwifi,mac80211

The iwlwifi module is in use and is also using iwlmvm.

modinfo

Now that we know what kernel module drivers our hardware is using we can get some info on it. The modinfo command will give us the info we want. Take a look at your modules information there is a lot to learn there. For this exercise we are going to specifically target getting the modules parameters. We can use the -F or --field flag with mod info, we will provide a field name and modinfo will only return info on that field.

# modinfo -F parm iwlmvm
init_dbg:set to true to debug an ASSERT in INIT fw (default: false (bool)
power_scheme:power management scheme: 1-active, 2-balanced, 3-low power, default: 2 (int)

We can see that the driver has a couple parameters that we can manipulate. We don't really care about init_dbg, but power_scheme sounds interesting. A little searching online reveals that this is the setting that determines when how aggressively to switch the wireless off to save power. Considering we are using the card in a desktop we don't need to worry about switching the wireless off, if the machine is on then we want the power to the wireless on.

Setting Module Parameters

modprobe.d

We can use configuration files in /etc/modprobe.d/ to set options for a module.

# echo "options iwlmvm power_scheme=1" > /etc/modprobe.d/iwlmvm.conf

Now let's unload and reload the module and see if it load the correct option.

# modprobe -r iwlmvm
# modprobe iwlmvm
cat /sys/module/iwlmvm/parameters/power_scheme
1

We can see that our module now has the option set to 1, always active. Because we created the config file, every time the module is loaded it will use that config.

btusb autosuspend

Similarly, we want to disable autosuspend on the btusb module since we are on a desktop and we don't need to suspend. This should at least help prevent unwanted disconnects.

# echo "options btusb enable_autosuspend=n" > /etc/modprobe.d/btusb.conf
# modprobe -r btusb
# modprobe btusb

Wrap Up

Manipulating the module settings is pretty straightforward and will offer us a lot of control over the system. It sounds like documentation on the options can be sparse #linux referred me to the kernel module source code as the documentation on the module parameter options, so I cloned the 5GB git repo for the Linux source. I didn't find much helpful for the iwlmvm module options. But it will be fun to dig into that more to learn more about the kernel/modules. There are a lot of modules loaded by the system (see below). We can start poking around at them now and figure out how else we might improve the system!

Module                  Size  Used by
iwlmvm                421888  0
iwlwifi               380928  1 iwlmvm
mac80211             1028096  1 iwlmvm
cfg80211              892928  3 iwlmvm,iwlwifi,mac80211
libarc4                16384  1 mac80211
binfmt_misc            24576  1
rfcomm                 81920  16
ipt_REJECT             16384  2
nf_reject_ipv4         16384  1 ipt_REJECT
xt_conntrack           16384  1
xt_comment             16384  17
xt_CHECKSUM            16384  2
nft_chain_nat          16384  4
xt_MASQUERADE          20480  4
nf_nat                 49152  2 nft_chain_nat,xt_MASQUERADE
nf_conntrack          147456  3 xt_conntrack,nf_nat,xt_MASQUERADE
nf_defrag_ipv6         24576  1 nf_conntrack
nf_defrag_ipv4         16384  1 nf_conntrack
nft_counter            16384  25
vboxnetadp             28672  0
vboxnetflt             28672  0
vboxdrv               516096  2 vboxnetadp,vboxnetflt
xt_tcpudp              20480  12
nft_compat             20480  38
nf_tables             212992  128 nft_compat,nft_counter,nft_chain_nat
libcrc32c              16384  3 nf_conntrack,nf_nat,nf_tables
nfnetlink              20480  2 nft_compat,nf_tables
vhost_vsock            24576  0
vmw_vsock_virtio_transport_common    40960  1 vhost_vsock
vhost                  53248  1 vhost_vsock
vhost_iotlb            16384  1 vhost
vsock                  45056  2 vmw_vsock_virtio_transport_common,vhost_vsock
ccm                    20480  9
cmac                   16384  3
algif_hash             16384  1
algif_skcipher         16384  1
af_alg                 32768  6 algif_hash,algif_skcipher
bnep                   28672  2
nls_iso8859_1          16384  1
nvidia_uvm           1048576  0
intel_rapl_msr         20480  0
nvidia_drm             61440  7
nvidia_modeset       1196032  14 nvidia_drm
intel_rapl_common      28672  1 intel_rapl_msr
x86_pkg_temp_thermal    20480  0
mei_hdcp               24576  0
intel_powerclamp       20480  0
coretemp               20480  0
crct10dif_pclmul       16384  1
ghash_clmulni_intel    16384  0
aesni_intel           372736  10
nvidia              35270656  710 nvidia_uvm,nvidia_modeset
crypto_simd            16384  1 aesni_intel
cryptd                 24576  3 crypto_simd,ghash_clmulni_intel
glue_helper            16384  1 aesni_intel
rapl                   20480  0
snd_hda_codec_realtek   147456  1
snd_hda_codec_generic    81920  1 snd_hda_codec_realtek
ledtrig_audio          16384  1 snd_hda_codec_generic
snd_hda_codec_hdmi     65536  1
snd_hda_intel          53248  4
snd_intel_dspcfg       28672  1 snd_hda_intel
soundwire_intel        40960  1 snd_intel_dspcfg
soundwire_generic_allocation    16384  1 soundwire_intel
soundwire_cadence      32768  1 soundwire_intel
snd_usb_audio         299008  3
snd_hda_codec         147456  4 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec_realtek
intel_cstate           20480  0
snd_usbmidi_lib        36864  1 snd_usb_audio
snd_hda_core           94208  5 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_hda_codec_realtek
snd_hwdep              16384  2 snd_usb_audio,snd_hda_codec
soundwire_bus          77824  3 soundwire_intel,soundwire_generic_allocation,soundwire_cadence
snd_seq_midi           20480  0
snd_soc_core          294912  1 soundwire_intel
snd_seq_midi_event     16384  1 snd_seq_midi
snd_seq                73728  2 snd_seq_midi,snd_seq_midi_event
snd_rawmidi            36864  2 snd_seq_midi,snd_usbmidi_lib
snd_compress           28672  1 snd_soc_core
ac97_bus               16384  1 snd_soc_core
snd_pcm_dmaengine      16384  1 snd_soc_core
mc                     57344  1 snd_usb_audio
snd_pcm               118784  9 snd_hda_codec_hdmi,snd_hda_intel,snd_usb_audio,snd_hda_codec,soundwire_intel,snd_compress,snd_soc_core,snd_hda_core,snd_pcm_dmaengine
btusb                  61440  0
serio_raw              20480  0
btrtl                  24576  1 btusb
btbcm                  16384  1 btusb
snd_seq_device         16384  3 snd_seq,snd_seq_midi,snd_rawmidi
eeepc_wmi              16384  0
wmi_bmof               16384  0
efi_pstore             16384  0
btintel                28672  1 btusb
intel_wmi_thunderbolt    20480  0
mxm_wmi                16384  0
ee1004                 20480  0
snd_timer              40960  2 snd_seq,snd_pcm
bluetooth             655360  43 btrtl,btintel,btbcm,bnep,btusb,rfcomm
drm_kms_helper        245760  1 nvidia_drm
snd                    94208  29 snd_hda_codec_generic,snd_seq,snd_seq_device,snd_hda_codec_hdmi,snd_hwdep,snd_hda_intel,snd_usb_audio,snd_usbmidi_lib,snd_hda_codec,snd_hda_codec_realtek,snd_timer,snd_compress,snd_soc_core,snd_pcm,snd_rawmidi
cec                    53248  1 drm_kms_helper
joydev                 28672  0
input_leds             16384  0
rc_core                57344  1 cec
mei_me                 40960  1
fb_sys_fops            16384  1 drm_kms_helper
syscopyarea            16384  1 drm_kms_helper
ecdh_generic           16384  2 bluetooth
sysfillrect            16384  1 drm_kms_helper
ecc                    32768  1 ecdh_generic
soundcore              16384  1 snd
mei                   126976  3 mei_hdcp,mei_me
sysimgblt              16384  1 drm_kms_helper
mac_hid                16384  0
acpi_pad              184320  0
sch_fq_codel           20480  4
uhid                   20480  0
kvm_intel             286720  0
kvm                   835584  1 kvm_intel
iptable_filter         16384  0
ip6table_filter        16384  0
ip6_tables             32768  1 ip6table_filter
br_netfilter           28672  0
bridge                249856  1 br_netfilter
stp                    16384  1 bridge
llc                    16384  2 bridge,stp
arp_tables             24576  0
msr                    16384  0
parport_pc             45056  0
ppdev                  24576  0
lp                     20480  0
parport                65536  3 parport_pc,lp,ppdev
drm                   552960  11 drm_kms_helper,nvidia,nvidia_drm
sunrpc                548864  1
ip_tables              32768  1 iptable_filter
x_tables               49152  12 ip6table_filter,xt_conntrack,iptable_filter,nft_compat,xt_tcpudp,xt_CHECKSUM,xt_comment,ip6_tables,ipt_REJECT,ip_tables,xt_MASQUERADE,arp_tables
autofs4                45056  4
hid_roccat_ryos        16384  0
hid_roccat             16384  1 hid_roccat_ryos
hid_roccat_common      16384  1 hid_roccat_ryos
hid_generic            16384  0
usbhid                 61440  1
hid                   135168  5 hid_roccat_ryos,usbhid,hid_generic,hid_roccat,uhid
mfd_aaeon              16384  0
asus_wmi               40960  2 eeepc_wmi,mfd_aaeon
sparse_keymap          16384  1 asus_wmi
crc32_pclmul           16384  0
psmouse               163840  0
nvme                   45056  2
e1000e                270336  0
i2c_i801               32768  0
nvme_core             122880  4 nvme
i2c_smbus              20480  1 i2c_i801
ahci                   40960  1
xhci_pci               20480  0
libahci                36864  1 ahci
xhci_pci_renesas       20480  1 xhci_pci
wmi                    32768  5 intel_wmi_thunderbolt,asus_wmi,wmi_bmof,mfd_aaeon,mxm_wmi
video                  53248  1 asus_wmi