You are not logged in.

#1 2020-02-09 18:06:17

cowboybebop
Member
Registered: 2020-02-08
Posts: 6

[SOLVED] WiFi not working, iwlwifi Microcode SW error detected

Hi everyone,
The WiFi on my laptop has not been working for the past couple of days after an update. I have tried googling around and couldn't find anything.
I have an Intel Wireless AC 8260 wireless card. I don't think that is a hardware issue as I tried booting with a liveUSB and the WiFi worked fine.  I think it might be a firmware error - please see the output of dmesg below.

[   36.928080] iwlwifi 0000:02:00.0: Firmware not running - cannot dump error
[   36.949861] iwlwifi 0000:02:00.0: Applying debug destination EXTERNAL_DRAM
[   37.103066] iwlwifi 0000:02:00.0: Applying debug destination EXTERNAL_DRAM
[   37.192690] iwlwifi 0000:02:00.0: FW already configured (0) - re-configuring
[   37.232291] iwlwifi 0000:02:00.0: Microcode SW error detected.  Restarting 0x2000000.
[   37.232540] iwlwifi 0000:02:00.0: Start IWL Error Log Dump:
[   37.232545] iwlwifi 0000:02:00.0: Status: 0x00000050, count: 6
[   37.232547] iwlwifi 0000:02:00.0: Loaded firmware version: 36.952d9faa.0
[   37.232551] iwlwifi 0000:02:00.0: 0x00000038 | BAD_COMMAND                 
[   37.232554] iwlwifi 0000:02:00.0: 0x00A002F1 | trm_hw_status0
[   37.232556] iwlwifi 0000:02:00.0: 0x00000000 | trm_hw_status1
[   37.232559] iwlwifi 0000:02:00.0: 0x00024200 | branchlink2
[   37.232561] iwlwifi 0000:02:00.0: 0x00039872 | interruptlink1
[   37.232563] iwlwifi 0000:02:00.0: 0x00000000 | interruptlink2
[   37.232566] iwlwifi 0000:02:00.0: 0x00250405 | data1
[   37.232568] iwlwifi 0000:02:00.0: 0x00000026 | data2
[   37.232570] iwlwifi 0000:02:00.0: 0x00000026 | data3
[   37.232573] iwlwifi 0000:02:00.0: 0x00000000 | beacon time
[   37.232575] iwlwifi 0000:02:00.0: 0x00010F27 | tsf low
[   37.232577] iwlwifi 0000:02:00.0: 0x00000000 | tsf hi
[   37.232580] iwlwifi 0000:02:00.0: 0x00000000 | time gp1
[   37.232582] iwlwifi 0000:02:00.0: 0x00010F28 | time gp2
[   37.232584] iwlwifi 0000:02:00.0: 0x00000001 | uCode revision type
[   37.232587] iwlwifi 0000:02:00.0: 0x00000024 | uCode version major
[   37.232590] iwlwifi 0000:02:00.0: 0x952D9FAA | uCode version minor
[   37.232592] iwlwifi 0000:02:00.0: 0x00000201 | hw version
[   37.232594] iwlwifi 0000:02:00.0: 0x18489008 | board version
[   37.232597] iwlwifi 0000:02:00.0: 0x00250405 | hcmd
[   37.232599] iwlwifi 0000:02:00.0: 0x00122080 | isr0
[   37.232601] iwlwifi 0000:02:00.0: 0x00000000 | isr1
[   37.232604] iwlwifi 0000:02:00.0: 0x28201802 | isr2
[   37.232606] iwlwifi 0000:02:00.0: 0x004000C0 | isr3
[   37.232608] iwlwifi 0000:02:00.0: 0x00000000 | isr4
[   37.232611] iwlwifi 0000:02:00.0: 0x0024019F | last cmd Id
[   37.232613] iwlwifi 0000:02:00.0: 0x00000000 | wait_event
[   37.232615] iwlwifi 0000:02:00.0: 0x0000955D | l2p_control
[   37.232618] iwlwifi 0000:02:00.0: 0x00000820 | l2p_duration
[   37.232620] iwlwifi 0000:02:00.0: 0x00000000 | l2p_mhvalid
[   37.232622] iwlwifi 0000:02:00.0: 0x00000000 | l2p_addr_match
[   37.232625] iwlwifi 0000:02:00.0: 0x0000000D | lmpm_pmg_sel
[   37.232627] iwlwifi 0000:02:00.0: 0x20111544 | timestamp
[   37.232629] iwlwifi 0000:02:00.0: 0x00002030 | flow_handler
[   37.232829] iwlwifi 0000:02:00.0: Start IWL Error Log Dump:
[   37.232832] iwlwifi 0000:02:00.0: Status: 0x00000050, count: 7
[   37.232835] iwlwifi 0000:02:00.0: 0x00000070 | NMI_INTERRUPT_LMAC_FATAL
[   37.232838] iwlwifi 0000:02:00.0: 0x00000000 | umac branchlink1
[   37.232840] iwlwifi 0000:02:00.0: 0xC0086B3C | umac branchlink2
[   37.232842] iwlwifi 0000:02:00.0: 0xC0083D08 | umac interruptlink1
[   37.232845] iwlwifi 0000:02:00.0: 0xC008096A | umac interruptlink2
[   37.232847] iwlwifi 0000:02:00.0: 0x00000800 | umac data1
[   37.232849] iwlwifi 0000:02:00.0: 0xC008096A | umac data2
[   37.232852] iwlwifi 0000:02:00.0: 0xDEADBEEF | umac data3
[   37.232854] iwlwifi 0000:02:00.0: 0x00000024 | umac major
[   37.232856] iwlwifi 0000:02:00.0: 0x952D9FAA | umac minor
[   37.232859] iwlwifi 0000:02:00.0: 0xC0887F3C | frame pointer
[   37.232861] iwlwifi 0000:02:00.0: 0xC0887F3C | stack pointer
[   37.232863] iwlwifi 0000:02:00.0: 0x00250405 | last host cmd
[   37.232866] iwlwifi 0000:02:00.0: 0x00004008 | isr status reg
[   37.233019] iwlwifi 0000:02:00.0: Fseq Registers:
[   37.233074] iwlwifi 0000:02:00.0: 0x68080C01 | FSEQ_ERROR_CODE
[   37.233129] iwlwifi 0000:02:00.0: 0x1A544410 | FSEQ_TOP_INIT_VERSION
[   37.233184] iwlwifi 0000:02:00.0: 0xDDC79D33 | FSEQ_CNVIO_INIT_VERSION
[   37.233239] iwlwifi 0000:02:00.0: 0x0000A056 | FSEQ_OTP_VERSION
[   37.233295] iwlwifi 0000:02:00.0: 0xBBE7D851 | FSEQ_TOP_CONTENT_VERSION
[   37.233350] iwlwifi 0000:02:00.0: 0x08520491 | FSEQ_ALIVE_TOKEN
[   37.233405] iwlwifi 0000:02:00.0: 0xF393E3A2 | FSEQ_CNVI_ID
[   37.233460] iwlwifi 0000:02:00.0: 0xA8261464 | FSEQ_CNVR_ID
[   37.233515] iwlwifi 0000:02:00.0: 0x03000000 | CNVI_AUX_MISC_CHIP
[   37.233573] iwlwifi 0000:02:00.0: 0x0BADCAFE | CNVR_AUX_MISC_CHIP
[   37.233631] iwlwifi 0000:02:00.0: 0x0BADCAFE | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM
[   37.233690] iwlwifi 0000:02:00.0: 0x0BADCAFE | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR
[   37.233745] iwlwifi 0000:02:00.0: Firmware error during reconfiguration - reprobe!
[   37.233792] iwlwifi 0000:02:00.0: LED command failed: -5
[   37.233825] iwlwifi 0000:02:00.0: FW error in SYNC CMD GEO_TX_POWER_LIMIT
[   37.233832] CPU: 2 PID: 454 Comm: NetworkManager Not tainted 5.5.2-arch1-1 #1
[   37.233835] iwlwifi 0000:02:00.0: LED command failed: -5
[   37.233838] Hardware name: ASUSTeK COMPUTER INC. UX330UAR/UX330UAR, BIOS UX330UAR.300 08/03/2017
[   37.233840] Call Trace:
[   37.233858]  dump_stack+0x66/0x90
[   37.233888]  iwl_trans_pcie_send_hcmd+0x45d/0x470 [iwlwifi]
[   37.233898]  ? wait_woken+0x70/0x70
[   37.233924]  iwl_trans_send_cmd+0x51/0xb0 [iwlwifi]
[   37.233948]  iwl_mvm_send_cmd+0x1b/0x40 [iwlmvm]
[   37.233967]  iwl_mvm_send_cmd_pdu+0x51/0x70 [iwlmvm]
[   37.233982]  iwl_mvm_up+0x8f4/0x930 [iwlmvm]
[   37.233999]  __iwl_mvm_mac_start+0x26/0x1c0 [iwlmvm]
[   37.234013]  iwl_mvm_mac_start+0x24/0x40 [iwlmvm]
[   37.234059]  drv_start+0x3e/0x130 [mac80211]
[   37.234101]  ieee80211_do_open+0x20b/0x850 [mac80211]
[   37.234137]  ? ieee80211_check_concurrent_iface+0x14f/0x1c0 [mac80211]
[   37.234145]  __dev_open+0xe0/0x170
[   37.234150]  __dev_change_flags+0x188/0x1e0
[   37.234155]  dev_change_flags+0x21/0x60
[   37.234161]  do_setlink+0x78a/0xf90
[   37.234175]  ? update_blocked_averages+0x213/0x5c0
[   37.234180]  ? cpumask_next_and+0x19/0x20
[   37.234184]  ? find_busiest_group+0x865/0xb30
[   37.234194]  ? cpumask_next+0x16/0x20
[   37.234204]  ? __snmp6_fill_stats64.isra.0+0x66/0x110
[   37.234217]  __rtnl_newlink+0x5d1/0x9a0
[   37.234256]  rtnl_newlink+0x44/0x70
[   37.234263]  rtnetlink_rcv_msg+0x137/0x3c0
[   37.234271]  ? rtnl_calcit.isra.0+0x120/0x120
[   37.234278]  netlink_rcv_skb+0x75/0x140
[   37.234286]  netlink_unicast+0x199/0x240
[   37.234293]  netlink_sendmsg+0x243/0x480
[   37.234303]  sock_sendmsg+0x5e/0x60
[   37.234309]  ____sys_sendmsg+0x21b/0x290
[   37.234315]  ? copy_msghdr_from_user+0xe1/0x160
[   37.234323]  ___sys_sendmsg+0x9e/0xe0
[   37.234340]  __sys_sendmsg+0x81/0xd0
[   37.234353]  do_syscall_64+0x4e/0x150
[   37.234362]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   37.234369] RIP: 0033:0x7f58ade987ed
[   37.234377] Code: 28 89 54 24 1c 48 89 74 24 10 89 7c 24 08 e8 4a 53 f8 ff 8b 54 24 1c 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 2f 44 89 c7 48 89 44 24 08 e8 7e 53 f8 ff 48
[   37.234380] RSP: 002b:00007fff83f23dd0 EFLAGS: 00000293 ORIG_RAX: 000000000000002e
[   37.234387] RAX: ffffffffffffffda RBX: 0000000000000416 RCX: 00007f58ade987ed
[   37.234390] RDX: 0000000000000000 RSI: 00007fff83f23e10 RDI: 000000000000000c
[   37.234393] RBP: 000055bd3112e070 R08: 0000000000000000 R09: 0000000000000000
[   37.234395] R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000000000
[   37.234398] R13: 00007fff83f23f70 R14: 00007fff83f23f6c R15: 0000000000000000

Here is the pacman log from the day before the WiFi stopped working.

[2020-02-05T21:38:08-0500] [PACMAN] starting full system upgrade
[2020-02-05T21:44:30-0500] [ALPM] running '60-mkinitcpio-remove.hook'...
[2020-02-05T21:44:30-0500] [ALPM] transaction started
[2020-02-05T21:44:30-0500] [ALPM] upgraded iana-etc (20191231-1 -> 20200117-1)
[2020-02-05T21:44:30-0500] [ALPM] upgraded libutil-linux (2.35-1 -> 2.35.1-1)
[2020-02-05T21:44:30-0500] [ALPM] upgraded libtasn1 (4.15.0-1 -> 4.16.0-1)
[2020-02-05T21:44:30-0500] [ALPM] upgraded cryptsetup (2.2.2-1 -> 2.3.0-1)
[2020-02-05T21:44:30-0500] [ALPM] upgraded shadow (4.8-1 -> 4.8.1-1)
[2020-02-05T21:44:30-0500] [ALPM] upgraded util-linux (2.35-1 -> 2.35.1-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded cmake (3.16.3-1 -> 3.16.4-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded gnutls (3.6.11.1-1 -> 3.6.12-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded xkeyboard-config (2.28-1 -> 2.29-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded girara (0.3.3-1 -> 0.3.4-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded imagemagick (7.0.9.20-1 -> 7.0.9.21-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded libmagick6 (6.9.10.90-1 -> 6.9.10.91-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded libmtp (1.1.16-1 -> 1.1.17-1)
[2020-02-05T21:44:31-0500] [ALPM] upgraded libsecret (0.20.0-1 -> 0.20.1-1)
[2020-02-05T21:44:32-0500] [ALPM] upgraded linux (5.4.15.arch1-1 -> 5.5.2.arch1-1)
[2020-02-05T21:44:33-0500] [ALPM] upgraded linux-firmware (20191220.6871bff-1 -> 20200122.1eb2408-1)
[2020-02-05T21:44:33-0500] [ALPM] upgraded s-nail (14.9.16-2 -> 14.9.17-1)
[2020-02-05T21:44:33-0500] [ALPM] upgraded sudo (1.8.30-1 -> 1.8.31-1)
[2020-02-05T21:44:33-0500] [ALPM] upgraded zathura (0.4.4-1 -> 0.4.5-1)
[2020-02-05T21:44:33-0500] [ALPM] transaction completed
[2020-02-05T21:44:33-0500] [ALPM] running '20-systemd-sysusers.hook'...
[2020-02-05T21:44:33-0500] [ALPM] running '30-systemd-daemon-reload.hook'...
[2020-02-05T21:44:33-0500] [ALPM] running '30-systemd-hwdb.hook'...
[2020-02-05T21:44:34-0500] [ALPM] running '30-systemd-tmpfiles.hook'...
[2020-02-05T21:44:34-0500] [ALPM] running '30-systemd-udev-reload.hook'...
[2020-02-05T21:44:34-0500] [ALPM] running '30-systemd-update.hook'...
[2020-02-05T21:44:34-0500] [ALPM] running '60-depmod.hook'...
[2020-02-05T21:44:40-0500] [ALPM] running '90-mkinitcpio-install.hook'...
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET] ==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET] ==> Starting build: 5.5.2-arch1-1
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [base]
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [udev]
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [autodetect]
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [modconf]
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [block]
[2020-02-05T21:44:40-0500] [ALPM-SCRIPTLET]   -> Running build hook: [filesystems]
[2020-02-05T21:44:41-0500] [ALPM-SCRIPTLET]   -> Running build hook: [keyboard]
[2020-02-05T21:44:41-0500] [ALPM-SCRIPTLET]   -> Running build hook: [fsck]
[2020-02-05T21:44:41-0500] [ALPM-SCRIPTLET] ==> Generating module dependencies
[2020-02-05T21:44:41-0500] [ALPM-SCRIPTLET] ==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET] ==> Image generation successful
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET] ==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'fallback'
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET]   -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux-fallback.img -S autodetect
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET] ==> Starting build: 5.5.2-arch1-1
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET]   -> Running build hook: [base]
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET]   -> Running build hook: [udev]
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET]   -> Running build hook: [modconf]
[2020-02-05T21:44:42-0500] [ALPM-SCRIPTLET]   -> Running build hook: [block]
[2020-02-05T21:44:43-0500] [ALPM-SCRIPTLET] ==> WARNING: Possibly missing firmware for module: wd719x
[2020-02-05T21:44:44-0500] [ALPM-SCRIPTLET] ==> WARNING: Possibly missing firmware for module: aic94xx
[2020-02-05T21:44:45-0500] [ALPM-SCRIPTLET]   -> Running build hook: [filesystems]
[2020-02-05T21:44:46-0500] [ALPM-SCRIPTLET]   -> Running build hook: [keyboard]
[2020-02-05T21:44:47-0500] [ALPM-SCRIPTLET]   -> Running build hook: [fsck]
[2020-02-05T21:44:48-0500] [ALPM-SCRIPTLET] ==> Generating module dependencies
[2020-02-05T21:44:48-0500] [ALPM-SCRIPTLET] ==> Creating gzip-compressed initcpio image: /boot/initramfs-linux-fallback.img
[2020-02-05T21:44:53-0500] [ALPM-SCRIPTLET] ==> Image generation successful
[2020-02-05T21:44:53-0500] [ALPM] running 'detect-old-perl-modules.hook'...
[2020-02-05T21:44:53-0500] [ALPM] running 'gtk-update-icon-cache.hook'...
[2020-02-05T21:44:53-0500] [ALPM] running 'texinfo-install.hook'...
[2020-02-05T21:44:53-0500] [ALPM] running 'update-desktop-database.hook'...
[2020-02-05T21:44:53-0500] [ALPM] running 'update-mime-database.hook'...

If you need any further information, please let me know. I would really appreciate it if you could let me point out to me how to fix the error. Thanks a lot.

EDIT: I downgraded the kernel. The WiFi seems to work fine now. It seems that there is a bug. See discussion https://bbs.archlinux.org/viewtopic.php?id=252676.

Last edited by cowboybebop (2020-02-09 18:20:40)

Offline

#2 2020-02-09 18:24:18

loqs
Member
Registered: 2014-03-06
Posts: 11,700

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

Your issue is not the 3168 issue.  See https://bugzilla.kernel.org/show_bug.cgi?id=206395
Unfortunately that report does not contain a git bisection to locate the cause and has not added linuxwifi@intel.com to the bug report
https://wireless.wiki.kernel.org/en/use … /debugging

Offline

#3 2020-02-09 18:57:22

cowboybebop
Member
Registered: 2020-02-08
Posts: 6

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

loqs wrote:

Your issue is not the 3168 issue.  See https://bugzilla.kernel.org/show_bug.cgi?id=206395
Unfortunately that report does not contain a git bisection to locate the cause and has not added linuxwifi@intel.com to the bug report
https://wireless.wiki.kernel.org/en/use … /debugging

Thanks a lot for pointing that out. I am sorry, I am a bit new to this. Do you suggest that I do anything other than add myself to the CC list?

Offline

#4 2020-02-09 19:15:22

loqs
Member
Registered: 2014-03-06
Posts: 11,700

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

First I would suggest checking linux 5.5.2.arch2-2 which contains the patch for the 3168 issue to make sure your system has a different issue.
Enable testing then update just linux i.e.

pacman -Sy linux

After testing you can then disable the testing repositories and downgrade the kernel again if the issue is still present.

Offline

#5 2020-02-09 19:37:15

cowboybebop
Member
Registered: 2020-02-08
Posts: 6

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

loqs wrote:

First I would suggest checking linux 5.5.2.arch2-2 which contains the patch for the 3168 issue to make sure your system has a different issue.
Enable testing then update just linux i.e.

pacman -Sy linux

After testing you can then disable the testing repositories and downgrade the kernel again if the issue is still present.

I checked out linux 5.5.2arch2-2 and the issue is still present.

Offline

#6 2020-02-10 12:40:23

loqs
Member
Registered: 2014-03-06
Posts: 11,700

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

This patch reverts some commits related to GEO_TX_POWER_LIMIT

git clone git://git.archlinux.org/svntogit/packages.git --single-branch --branch "packages/linux"
cd packages/linux

Create iwlwifi.patch in this directory with the contents from below.
Edit PKGBUILD adding iwlwifi.patch to the sources array i.e

source=(
  "$_srcname::git+https://git.archlinux.org/linux.git?signed#tag=$_srctag"
  config         # the main kernel config file
  iwlwifi.patch
)
updpkgsums #provided by pacman-contrib to add the checksum for the patch
makepkg -rs  #build the package
pacman -U linux-5.5.2.arch2-2-x86_64.pkg.tar.xz #install the just built kernel

iwlwifi.patch

diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index 48d375a86d86..c2db758b9d54 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -61,7 +61,6 @@
 #include "iwl-drv.h"
 #include "iwl-debug.h"
 #include "acpi.h"
-#include "fw/runtime.h"
 
 void *iwl_acpi_get_object(struct device *dev, acpi_string method)
 {
@@ -246,289 +245,3 @@ int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
 	return ret;
 }
 IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
-
-int iwl_sar_set_profile(union acpi_object *table,
-			struct iwl_sar_profile *profile,
-			bool enabled)
-{
-	int i;
-
-	profile->enabled = enabled;
-
-	for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
-		if (table[i].type != ACPI_TYPE_INTEGER ||
-		    table[i].integer.value > U8_MAX)
-			return -EINVAL;
-
-		profile->table[i] = table[i].integer.value;
-	}
-
-	return 0;
-}
-IWL_EXPORT_SYMBOL(iwl_sar_set_profile);
-
-int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
-			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
-			   int prof_a, int prof_b)
-{
-	int i, j, idx;
-	int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
-
-	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
-	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
-		     ACPI_SAR_TABLE_SIZE);
-
-	for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
-		struct iwl_sar_profile *prof;
-
-		/* don't allow SAR to be disabled (profile 0 means disable) */
-		if (profs[i] == 0)
-			return -EPERM;
-
-		/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
-		if (profs[i] > ACPI_SAR_PROFILE_NUM)
-			return -EINVAL;
-
-		/* profiles go from 1 to 4, so decrement to access the array */
-		prof = &fwrt->sar_profiles[profs[i] - 1];
-
-		/* if the profile is disabled, do nothing */
-		if (!prof->enabled) {
-			IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
-					profs[i]);
-			/* if one of the profiles is disabled, we fail all */
-			return -ENOENT;
-		}
-		IWL_DEBUG_INFO(fwrt,
-			       "SAR EWRD: chain %d profile index %d\n",
-			       i, profs[i]);
-		IWL_DEBUG_RADIO(fwrt, "  Chain[%d]:\n", i);
-		for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
-			idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
-			per_chain_restriction[i][j] =
-				cpu_to_le16(prof->table[idx]);
-			IWL_DEBUG_RADIO(fwrt, "    Band[%d] = %d * .125dBm\n",
-					j, prof->table[idx]);
-		}
-	}
-
-	return 0;
-}
-IWL_EXPORT_SYMBOL(iwl_sar_select_profile);
-
-int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
-{
-	union acpi_object *wifi_pkg, *table, *data;
-	bool enabled;
-	int ret, tbl_rev;
-
-	data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDS_METHOD);
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-
-	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
-					 ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
-	if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
-		ret = PTR_ERR(wifi_pkg);
-		goto out_free;
-	}
-
-	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-
-	enabled = !!(wifi_pkg->package.elements[1].integer.value);
-
-	/* position of the actual table */
-	table = &wifi_pkg->package.elements[2];
-
-	/* The profile from WRDS is officially profile 1, but goes
-	 * into sar_profiles[0] (because we don't have a profile 0).
-	 */
-	ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled);
-out_free:
-	kfree(data);
-	return ret;
-}
-IWL_EXPORT_SYMBOL(iwl_sar_get_wrds_table);
-
-int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
-{
-	union acpi_object *wifi_pkg, *data;
-	bool enabled;
-	int i, n_profiles, tbl_rev, pos;
-	int ret = 0;
-
-	data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD);
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-
-	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
-					 ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
-	if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
-		ret = PTR_ERR(wifi_pkg);
-		goto out_free;
-	}
-
-	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
-	    wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-
-	enabled = !!(wifi_pkg->package.elements[1].integer.value);
-	n_profiles = wifi_pkg->package.elements[2].integer.value;
-
-	/*
-	 * Check the validity of n_profiles.  The EWRD profiles start
-	 * from index 1, so the maximum value allowed here is
-	 * ACPI_SAR_PROFILES_NUM - 1.
-	 */
-	if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
-		ret = -EINVAL;
-		goto out_free;
-	}
-
-	/* the tables start at element 3 */
-	pos = 3;
-
-	for (i = 0; i < n_profiles; i++) {
-		/* The EWRD profiles officially go from 2 to 4, but we
-		 * save them in sar_profiles[1-3] (because we don't
-		 * have profile 0).  So in the array we start from 1.
-		 */
-		ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos],
-					  &fwrt->sar_profiles[i + 1],
-					  enabled);
-		if (ret < 0)
-			break;
-
-		/* go to the next table */
-		pos += ACPI_SAR_TABLE_SIZE;
-	}
-
-out_free:
-	kfree(data);
-	return ret;
-}
-IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table);
-
-int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
-{
-	union acpi_object *wifi_pkg, *data;
-	int i, j, ret, tbl_rev;
-	int idx = 1;
-
-	data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD);
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-
-	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
-					 ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
-	if (IS_ERR(wifi_pkg) || tbl_rev > 1) {
-		ret = PTR_ERR(wifi_pkg);
-		goto out_free;
-	}
-
-	fwrt->geo_rev = tbl_rev;
-	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
-		for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
-			union acpi_object *entry;
-
-			entry = &wifi_pkg->package.elements[idx++];
-			if (entry->type != ACPI_TYPE_INTEGER ||
-			    entry->integer.value > U8_MAX) {
-				ret = -EINVAL;
-				goto out_free;
-			}
-
-			fwrt->geo_profiles[i].values[j] = entry->integer.value;
-		}
-	}
-	ret = 0;
-out_free:
-	kfree(data);
-	return ret;
-}
-IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);
-
-bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
-{
-	/*
-	 * The GEO_TX_POWER_LIMIT command is not supported on earlier
-	 * firmware versions.  Unfortunately, we don't have a TLV API
-	 * flag to rely on, so rely on the major version which is in
-	 * the first byte of ucode_ver.  This was implemented
-	 * initially on version 38 and then backported to 17.  It was
-	 * also backported to 29, but only for 7265D devices.  The
-	 * intention was to have it in 36 as well, but not all 8000
-	 * family got this feature enabled.  The 8000 family is the
-	 * only one using version 36, so skip this version entirely.
-	 */
-	return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
-	       IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 ||
-	       (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
-		((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
-		 CSR_HW_REV_TYPE_7265D));
-}
-IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
-
-int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
-				 struct iwl_host_cmd *cmd)
-{
-	struct iwl_geo_tx_power_profiles_resp *resp;
-	int ret;
-
-	resp = (void *)cmd->resp_pkt->data;
-	ret = le32_to_cpu(resp->profile_idx);
-	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
-		ret = -EIO;
-		IWL_WARN(fwrt, "Invalid geographic profile idx (%d)\n", ret);
-	}
-
-	return ret;
-}
-IWL_EXPORT_SYMBOL(iwl_validate_sar_geo_profile);
-
-void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
-		      struct iwl_per_chain_offset_group *table)
-{
-	int ret, i, j;
-
-	if (!iwl_sar_geo_support(fwrt))
-		return;
-
-	ret = iwl_sar_get_wgds_table(fwrt);
-	if (ret < 0) {
-		IWL_DEBUG_RADIO(fwrt,
-				"Geo SAR BIOS table invalid or unavailable. (%d)\n",
-				ret);
-		/* we don't fail if the table is not available */
-		return;
-	}
-
-	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
-		     ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);
-
-	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
-
-	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
-		struct iwl_per_chain_offset *chain =
-			(struct iwl_per_chain_offset *)&table[i];
-
-		for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
-			u8 *value;
-
-			value = &fwrt->geo_profiles[i].values[j *
-				ACPI_GEO_PER_CHAIN_SIZE];
-			chain[j].max_tx_power = cpu_to_le16(value[0]);
-			chain[j].chain_a = value[1];
-			chain[j].chain_b = value[2];
-			IWL_DEBUG_RADIO(fwrt,
-					"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
-					i, j, value[1], value[2], value[0]);
-		}
-	}
-}
-IWL_EXPORT_SYMBOL(iwl_sar_geo_init);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 4a6e8262974b..6cb2d1f5efea 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -61,12 +61,6 @@
 #define __iwl_fw_acpi__
 
 #include <linux/acpi.h>
-#include "fw/api/commands.h"
-#include "fw/api/power.h"
-#include "fw/api/phy.h"
-#include "fw/img.h"
-#include "iwl-trans.h"
-
 
 #define ACPI_WRDS_METHOD	"WRDS"
 #define ACPI_EWRD_METHOD	"EWRD"
@@ -110,21 +104,9 @@
 #define ACPI_PPAG_MIN_HB -16
 #define ACPI_PPAG_MAX_HB 40
 
-struct iwl_sar_profile {
-	bool enabled;
-	u8 table[ACPI_SAR_TABLE_SIZE];
-};
-
-struct iwl_geo_profile {
-	u8 values[ACPI_GEO_TABLE_SIZE];
-};
-
 #ifdef CONFIG_ACPI
 
-struct iwl_fw_runtime;
-
 void *iwl_acpi_get_object(struct device *dev, acpi_string method);
-
 union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
 					 union acpi_object *data,
 					 int data_size, int *tbl_rev);
@@ -152,27 +134,6 @@ u64 iwl_acpi_get_pwr_limit(struct device *dev);
  */
 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
 
-int iwl_sar_set_profile(union acpi_object *table,
-			struct iwl_sar_profile *profile,
-			bool enabled);
-
-int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
-			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
-			   int prof_a, int prof_b);
-
-int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt);
-
-int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt);
-
-int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
-
-bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
-
-int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
-				 struct iwl_host_cmd *cmd);
-
-void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
-		      struct iwl_per_chain_offset_group *table);
 #else /* CONFIG_ACPI */
 
 static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
@@ -203,50 +164,5 @@ static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
 	return -ENOENT;
 }
 
-static inline int iwl_sar_set_profile(union acpi_object *table,
-				      struct iwl_sar_profile *profile,
-				      bool enabled)
-{
-	return -ENOENT;
-}
-
-static inline int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
-			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
-			   int prof_a, int prof_b)
-{
-	return -ENOENT;
-}
-
-static inline int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
-{
-	return -ENOENT;
-}
-
-static inline int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
-{
-	return -ENOENT;
-}
-
-static inline int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
-{
-	return -ENOENT;
-}
-
-static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
-{
-	return false;
-}
-
-static inline int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
-					       struct iwl_host_cmd *cmd)
-{
-	return -ENOENT;
-}
-
-static inline void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
-				    struct iwl_per_chain_offset_group *table)
-{
-}
-
 #endif /* CONFIG_ACPI */
 #endif /* __iwl_fw_acpi__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index c24575ff0e54..ec2ab0281f18 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -65,9 +65,7 @@
 #include "img.h"
 #include "fw/api/debug.h"
 #include "fw/api/paging.h"
-#include "fw/api/power.h"
 #include "iwl-eeprom-parse.h"
-#include "fw/acpi.h"
 
 #define IWL_FW_DBG_DOMAIN		IWL_FW_INI_DOMAIN_ALWAYS_ON
 
@@ -205,16 +203,7 @@ struct iwl_fw_runtime {
 		u32 delay;
 		u64 seq;
 	} timestamp;
-	bool tpc_enabled;
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
-#ifdef CONFIG_ACPI
-	struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
-	u8 sar_chain_a_profile;
-	u8 sar_chain_b_profile;
-	struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
-	u32 geo_rev;
-	struct iwl_ppag_table_cmd ppag_table;
-#endif
 };
 
 void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index aa659162a7c2..f88033518f9d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -378,7 +378,7 @@ static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
 		pos = scnprintf(buf, bufsz,
 				"SAR geographic profile disabled\n");
 	} else {
-		value = &mvm->fwrt.geo_profiles[tbl_idx - 1].values[0];
+		value = &mvm->geo_profiles[tbl_idx - 1].values[0];
 
 		pos += scnprintf(buf + pos, bufsz - pos,
 				 "Use geographic profile %d\n", tbl_idx);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index c09624d8d7ee..66e14f590b6d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -678,14 +678,181 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
 }
 
 #ifdef CONFIG_ACPI
+static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
+					  union acpi_object *table,
+					  struct iwl_mvm_sar_profile *profile,
+					  bool enabled)
+{
+	int i;
+
+	profile->enabled = enabled;
+
+	for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
+		if ((table[i].type != ACPI_TYPE_INTEGER) ||
+		    (table[i].integer.value > U8_MAX))
+			return -EINVAL;
+
+		profile->table[i] = table[i].integer.value;
+	}
+
+	return 0;
+}
+
+static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
+{
+	union acpi_object *wifi_pkg, *table, *data;
+	bool enabled;
+	int ret, tbl_rev;
+
+	data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+					 ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
+	if (IS_ERR(wifi_pkg)) {
+		ret = PTR_ERR(wifi_pkg);
+		goto out_free;
+	}
+
+	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
+	    tbl_rev != 0) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	enabled = !!(wifi_pkg->package.elements[1].integer.value);
+
+	/* position of the actual table */
+	table = &wifi_pkg->package.elements[2];
+
+	/* The profile from WRDS is officially profile 1, but goes
+	 * into sar_profiles[0] (because we don't have a profile 0).
+	 */
+	ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0],
+				      enabled);
+out_free:
+	kfree(data);
+	return ret;
+}
+
+static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
+{
+	union acpi_object *wifi_pkg, *data;
+	bool enabled;
+	int i, n_profiles, ret, tbl_rev;
+
+	data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+					 ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
+	if (IS_ERR(wifi_pkg)) {
+		ret = PTR_ERR(wifi_pkg);
+		goto out_free;
+	}
+
+	if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) ||
+	    (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) ||
+	    tbl_rev != 0) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	enabled = !!(wifi_pkg->package.elements[1].integer.value);
+	n_profiles = wifi_pkg->package.elements[2].integer.value;
+
+	/*
+	 * Check the validity of n_profiles.  The EWRD profiles start
+	 * from index 1, so the maximum value allowed here is
+	 * ACPI_SAR_PROFILES_NUM - 1.
+	 */
+	if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	for (i = 0; i < n_profiles; i++) {
+		/* the tables start at element 3 */
+		int pos = 3;
+
+		/* The EWRD profiles officially go from 2 to 4, but we
+		 * save them in sar_profiles[1-3] (because we don't
+		 * have profile 0).  So in the array we start from 1.
+		 */
+		ret = iwl_mvm_sar_set_profile(mvm,
+					      &wifi_pkg->package.elements[pos],
+					      &mvm->sar_profiles[i + 1],
+					      enabled);
+		if (ret < 0)
+			break;
+
+		/* go to the next table */
+		pos += ACPI_SAR_TABLE_SIZE;
+	}
+
+out_free:
+	kfree(data);
+	return ret;
+}
+
+static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
+{
+	union acpi_object *wifi_pkg, *data;
+	int i, j, ret, tbl_rev;
+	int idx = 1;
+
+	data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+					 ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
+	if (IS_ERR(wifi_pkg)) {
+		ret = PTR_ERR(wifi_pkg);
+		goto out_free;
+	}
+
+	if (tbl_rev != 0) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	mvm->geo_rev = tbl_rev;
+	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
+		for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
+			union acpi_object *entry;
+
+			entry = &wifi_pkg->package.elements[idx++];
+			if ((entry->type != ACPI_TYPE_INTEGER) ||
+			    (entry->integer.value > U8_MAX)) {
+				ret = -EINVAL;
+				goto out_free;
+			}
+
+			mvm->geo_profiles[i].values[j] = entry->integer.value;
+		}
+	}
+	ret = 0;
+out_free:
+	kfree(data);
+	return ret;
+}
+
 int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
 {
 	union {
 		struct iwl_dev_tx_power_cmd v5;
 		struct iwl_dev_tx_power_cmd_v4 v4;
 	} cmd;
+	int i, j, idx;
+	int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
+	int len;
 
-	u16 len = 0;
+	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
+	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
+		     ACPI_SAR_TABLE_SIZE);
 
 	cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS);
 
@@ -694,76 +861,174 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
 		len = sizeof(cmd.v5);
 	else if (fw_has_capa(&mvm->fw->ucode_capa,
 			     IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
-		len = sizeof(struct iwl_dev_tx_power_cmd_v4);
+		len = sizeof(cmd.v4);
 	else
 		len = sizeof(cmd.v4.v3);
 
+	for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
+		struct iwl_mvm_sar_profile *prof;
+
+		/* don't allow SAR to be disabled (profile 0 means disable) */
+		if (profs[i] == 0)
+			return -EPERM;
+
+		/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
+		if (profs[i] > ACPI_SAR_PROFILE_NUM)
+			return -EINVAL;
+
+		/* profiles go from 1 to 4, so decrement to access the array */
+		prof = &mvm->sar_profiles[profs[i] - 1];
+
+		/* if the profile is disabled, do nothing */
+		if (!prof->enabled) {
+			IWL_DEBUG_RADIO(mvm, "SAR profile %d is disabled.\n",
+					profs[i]);
+			/* if one of the profiles is disabled, we fail all */
+			return -ENOENT;
+		}
+
+		IWL_DEBUG_INFO(mvm,
+			       "SAR EWRD: chain %d profile index %d\n",
+			       i, profs[i]);
+		IWL_DEBUG_RADIO(mvm, "  Chain[%d]:\n", i);
+		for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
+			idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
+			cmd.v5.v3.per_chain_restriction[i][j] =
+				cpu_to_le16(prof->table[idx]);
+			IWL_DEBUG_RADIO(mvm, "    Band[%d] = %d * .125dBm\n",
+					j, prof->table[idx]);
+		}
+	}
 
-	if (iwl_sar_select_profile(&mvm->fwrt, cmd.v5.v3.per_chain_restriction,
-				   prof_a, prof_b))
-		return -ENOENT;
 	IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
+
 	return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
 }
 
+static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
+{
+	/*
+	 * The GEO_TX_POWER_LIMIT command is not supported on earlier
+	 * firmware versions.  Unfortunately, we don't have a TLV API
+	 * flag to rely on, so rely on the major version which is in
+	 * the first byte of ucode_ver.  This was implemented
+	 * initially on version 38 and then backported to 17.  It was
+	 * also backported to 29, but only for 7265D devices.  The
+	 * intention was to have it in 36 as well, but not all 8000
+	 * family got this feature enabled.  The 8000 family is the
+	 * only one using version 36, so skip this version entirely.
+	 */
+	return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
+	       IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 ||
+	       (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 &&
+		((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
+		 CSR_HW_REV_TYPE_7265D));
+}
+
 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
 {
-	union geo_tx_power_profiles_cmd geo_tx_cmd;
-	u16 len;
+	struct iwl_geo_tx_power_profiles_resp *resp;
 	int ret;
+	u16 len;
+	void *data;
+	struct iwl_geo_tx_power_profiles_cmd geo_cmd;
+	struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
 	struct iwl_host_cmd cmd;
 
-	if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
-		       IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
-		geo_tx_cmd.geo_cmd.ops =
+	if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
+		geo_cmd.ops =
 			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
-		len = sizeof(geo_tx_cmd.geo_cmd);
+		len = sizeof(geo_cmd);
+		data = &geo_cmd;
 	} else {
-		geo_tx_cmd.geo_cmd_v1.ops =
+		geo_cmd_v1.ops =
 			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
-		len = sizeof(geo_tx_cmd.geo_cmd_v1);
+		len = sizeof(geo_cmd_v1);
+		data = &geo_cmd_v1;
 	}
 
-	if (!iwl_sar_geo_support(&mvm->fwrt))
-		return -EOPNOTSUPP;
-
 	cmd = (struct iwl_host_cmd){
 		.id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
 		.len = { len, },
 		.flags = CMD_WANT_SKB,
-		.data = { &geo_tx_cmd },
+		.data = { data },
 	};
 
+	if (!iwl_mvm_sar_geo_support(mvm))
+		return -EOPNOTSUPP;
+
 	ret = iwl_mvm_send_cmd(mvm, &cmd);
 	if (ret) {
 		IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
 		return ret;
 	}
-	ret = iwl_validate_sar_geo_profile(&mvm->fwrt, &cmd);
+
+	resp = (void *)cmd.resp_pkt->data;
+	ret = le32_to_cpu(resp->profile_idx);
+	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
+		ret = -EIO;
+		IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
+	}
+
 	iwl_free_resp(&cmd);
 	return ret;
 }
 
 static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
 {
+	struct iwl_geo_tx_power_profiles_cmd cmd = {
+		.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
+	};
+	int ret, i, j;
 	u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
-	union geo_tx_power_profiles_cmd cmd;
-	u16 len;
 
-	cmd.geo_cmd.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
+	if (!iwl_mvm_sar_geo_support(mvm))
+		return 0;
 
-	iwl_sar_geo_init(&mvm->fwrt, cmd.geo_cmd.table);
+	ret = iwl_mvm_sar_get_wgds_table(mvm);
+	if (ret < 0) {
+		IWL_DEBUG_RADIO(mvm,
+				"Geo SAR BIOS table invalid or unavailable. (%d)\n",
+				ret);
+		/* we don't fail if the table is not available */
+		return 0;
+	}
 
-	cmd.geo_cmd.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
+	IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
 
-	if (!fw_has_api(&mvm->fwrt.fw->ucode_capa,
-			IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
-		len = sizeof(struct iwl_geo_tx_power_profiles_cmd_v1);
-	} else {
-		len =  sizeof(cmd.geo_cmd);
+	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
+		     ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);
+
+	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
+
+	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
+		struct iwl_per_chain_offset *chain =
+			(struct iwl_per_chain_offset *)&cmd.table[i];
+
+		for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
+			u8 *value;
+
+			value = &mvm->geo_profiles[i].values[j *
+				ACPI_GEO_PER_CHAIN_SIZE];
+			chain[j].max_tx_power = cpu_to_le16(value[0]);
+			chain[j].chain_a = value[1];
+			chain[j].chain_b = value[2];
+			IWL_DEBUG_RADIO(mvm,
+					"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
+					i, j, value[1], value[2], value[0]);
+		}
+	}
+
+	cmd.table_revision = cpu_to_le32(mvm->geo_rev);
+
+	if (!fw_has_api(&mvm->fw->ucode_capa,
+		       IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
+		return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0,
+				sizeof(struct iwl_geo_tx_power_profiles_cmd_v1),
+				&cmd);
 	}
 
-	return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, len, &cmd);
+	return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
 }
 
 static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
@@ -772,7 +1037,7 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
 	int i, j, ret, tbl_rev;
 	int idx = 2;
 
-	mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
+	mvm->ppag_table.enabled = cpu_to_le32(0);
 	data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
 	if (IS_ERR(data))
 		return PTR_ERR(data);
@@ -797,8 +1062,8 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
 		goto out_free;
 	}
 
-	mvm->fwrt.ppag_table.enabled = cpu_to_le32(enabled->integer.value);
-	if (!mvm->fwrt.ppag_table.enabled) {
+	mvm->ppag_table.enabled = cpu_to_le32(enabled->integer.value);
+	if (!mvm->ppag_table.enabled) {
 		ret = 0;
 		goto out_free;
 	}
@@ -818,11 +1083,11 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
 			    (j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
 			    (j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
 			    (j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
-				mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
+				mvm->ppag_table.enabled = cpu_to_le32(0);
 				ret = -EINVAL;
 				goto out_free;
 			}
-			mvm->fwrt.ppag_table.gain[i][j] = ent->integer.value;
+			mvm->ppag_table.gain[i][j] = ent->integer.value;
 		}
 	}
 	ret = 0;
@@ -841,26 +1106,22 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
 		return 0;
 	}
 
-	if (!mvm->fwrt.ppag_table.enabled) {
-		IWL_DEBUG_RADIO(mvm,
-				"PPAG not enabled, command not sent.\n");
-		return 0;
-	}
-
 	IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
+	IWL_DEBUG_RADIO(mvm, "PPAG is %s\n",
+			mvm->ppag_table.enabled ? "enabled" : "disabled");
 
 	for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
 		for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
 			IWL_DEBUG_RADIO(mvm,
 					"PPAG table: chain[%d] band[%d]: gain = %d\n",
-					i, j, mvm->fwrt.ppag_table.gain[i][j]);
+					i, j, mvm->ppag_table.gain[i][j]);
 		}
 	}
 
 	ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
 						PER_PLATFORM_ANT_GAIN_CMD),
-				   0, sizeof(mvm->fwrt.ppag_table),
-				   &mvm->fwrt.ppag_table);
+				   0, sizeof(mvm->ppag_table),
+				   &mvm->ppag_table);
 	if (ret < 0)
 		IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
 			ret);
@@ -883,14 +1144,17 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
 }
 
 #else /* CONFIG_ACPI */
+static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
+{
+	return -ENOENT;
+}
 
-inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
-				      int prof_a, int prof_b)
+static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
 {
 	return -ENOENT;
 }
 
-inline int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
 {
 	return -ENOENT;
 }
@@ -900,6 +1164,17 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
 	return 0;
 }
 
+int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a,
+			       int prof_b)
+{
+	return -ENOENT;
+}
+
+int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
+{
+	return -ENOENT;
+}
+
 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
 {
 	return -ENOENT;
@@ -907,7 +1182,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
 
 static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
 {
-	return 0;
+	return -ENOENT;
 }
 #endif /* CONFIG_ACPI */
 
@@ -966,7 +1241,7 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
 {
 	int ret;
 
-	ret = iwl_sar_get_wrds_table(&mvm->fwrt);
+	ret = iwl_mvm_sar_get_wrds_table(mvm);
 	if (ret < 0) {
 		IWL_DEBUG_RADIO(mvm,
 				"WRDS SAR BIOS table invalid or unavailable. (%d)\n",
@@ -978,14 +1253,16 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
 		return 1;
 	}
 
-	ret = iwl_sar_get_ewrd_table(&mvm->fwrt);
+	ret = iwl_mvm_sar_get_ewrd_table(mvm);
 	/* if EWRD is not available, we can still use WRDS, so don't fail */
 	if (ret < 0)
 		IWL_DEBUG_RADIO(mvm,
 				"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
 				ret);
 
+	/* choose profile 1 (WRDS) as default for both chains */
 	ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
+
 	/*
 	 * If we don't have profile 0 from BIOS, just skip it.  This
 	 * means that SAR Geo will not be enabled either, even if we
@@ -1216,7 +1493,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
 	ret = iwl_mvm_sar_init(mvm);
 	if (ret == 0) {
 		ret = iwl_mvm_sar_geo_init(mvm);
-	} else if (ret > 0 && !iwl_sar_get_wgds_table(&mvm->fwrt)) {
+	} else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) {
 		/*
 		 * If basic SAR is not available, we check for WGDS,
 		 * which should *not* be available either.  If it is
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 67ab7e7e9c9d..1311d0e561fc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -188,11 +188,6 @@ enum iwl_power_scheme {
 	IWL_POWER_SCHEME_LP
 };
 
-union geo_tx_power_profiles_cmd {
-	struct iwl_geo_tx_power_profiles_cmd geo_cmd;
-	struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
-};
-
 #define IWL_CONN_MAX_LISTEN_INTERVAL	10
 #define IWL_UAPSD_MAX_SP		IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
 
@@ -779,6 +774,14 @@ enum iwl_mvm_queue_status {
 
 #define IWL_MVM_NUM_CIPHERS             10
 
+struct iwl_mvm_sar_profile {
+	bool enabled;
+	u8 table[ACPI_SAR_TABLE_SIZE];
+};
+
+struct iwl_mvm_geo_profile {
+	u8 values[ACPI_GEO_TABLE_SIZE];
+};
 
 struct iwl_mvm_txq {
 	struct list_head list;
@@ -1141,6 +1144,14 @@ struct iwl_mvm {
 	/* sniffer data to include in radiotap */
 	__le16 cur_aid;
 	u8 cur_bssid[ETH_ALEN];
+
+#ifdef CONFIG_ACPI
+	struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
+	struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
+	u32 geo_rev;
+	struct iwl_ppag_table_cmd ppag_table;
+	u32 ppag_rev;
+#endif
 };
 
 /* Extract MVM priv from op_mode and _hw */

Offline

#7 2020-02-10 19:22:59

cowboybebop
Member
Registered: 2020-02-08
Posts: 6

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

This patch works. Thanks a lot!

P.S. In case anyone is going to try this out, it should be

cd packages/trunk

instead of

cd packages/linux

Offline

#8 2020-02-11 22:14:02

c4rr0t
Member
Registered: 2020-02-11
Posts: 5

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

This worked for me as well. Thank you all!!!

Offline

#9 2020-02-12 11:52:10

apholden
Member
Registered: 2020-01-15
Posts: 5

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

It looks like linux-5.5.3-arch1-1 was fixed, or at least it works for me.  Thanks, everyone, for figuring this out!

Offline

#10 2020-03-02 15:06:38

Valentin Melot
Member
Registered: 2020-01-16
Posts: 4

Re: [SOLVED] WiFi not working, iwlwifi Microcode SW error detected

Hi, I’ve been experiencing exactly the same bug, except I’m using 5.5.7, and downgrading did not solve the issue. I opened a new topic there: https://bbs.archlinux.org/viewtopic.php?id=253303.

Offline

Board footer

Powered by FluxBB