You are not logged in.
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
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
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
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
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
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
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
This worked for me as well. Thank you all!!!
Offline
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
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