Re: [PATCH] Revert "wlcore: Adding suppoprt for IGTK key in wlcore driver"

From: Mauro Carvalho Chehab
Date: Fri Aug 28 2020 - 04:31:45 EST


Em Thu, 27 Aug 2020 13:36:28 -0700
Steve deRosier <derosier@xxxxxxxxx> escreveu:

> Hi Mauro,
>
> On Thu, Aug 27, 2020 at 10:42 AM Mauro Carvalho Chehab
> <mchehab+huawei@xxxxxxxxxx> wrote:
> >
> > Em Thu, 27 Aug 2020 08:48:30 -0700
> > Steve deRosier <derosier@xxxxxxxxx> escreveu:
> >
> > > On Tue, Aug 25, 2020 at 10:49 PM Mauro Carvalho Chehab
> > > <mchehab+huawei@xxxxxxxxxx> wrote:
> > > >
> > > > This patch causes a regression betwen Kernel 5.7 and 5.8 at wlcore:
> > > > with it applied, WiFi stops working, and the Kernel starts printing
> > > > this message every second:
> > > >
> > > > wlcore: PHY firmware version: Rev 8.2.0.0.242
> > > > wlcore: firmware booted (Rev 8.9.0.0.79)
> > > > wlcore: ERROR command execute failure 14
> > >
> > > Only if NO firmware for the device in question supports the `KEY_IGTK`
> > > value, then this revert is appropriate. Otherwise, it likely isn't.
> >
> > Yeah, that's what I suspect too: some specific firmware is required
> > for KEY_IGTK to work.
> >
> > > My suspicion is that the feature that `KEY_IGTK` is enabling is
> > > specific to a newer firmware that Mauro hasn't upgraded to. What the
> > > OP should do is find the updated firmware and give it a try.
> >
> > I didn't try checking if linux-firmware tree has a newer version on
> > it. I'm using Debian Bullseye on this device. So, I suspect that
> > it may have a relatively new firmware.
> >
> > Btw, that's also the version that came together with Fedora 32:
> >
> > $ strings /lib/firmware/ti-connectivity/wl18xx-fw-4.bin |grep FRev
> > FRev 8.9.0.0.79
> > FRev 8.2.0.0.242
> >
> > Looking at:
> > https://git.ti.com/cgit/wilink8-wlan/wl18xx_fw/
> >
> > It sounds that there's a newer version released this year:
> >
> > 2020-05-28 Updated to FW 8.9.0.0.81
> > 2018-07-29 Updated to FW 8.9.0.0.79
> >
> > However, it doesn't reached linux-firmware upstream yet:
> >
> > $ git log --pretty=oneline ti-connectivity/wl18xx-fw-4.bin
> > 3a5103fc3c29 wl18xx: update firmware file 8.9.0.0.79
> > 65b1c68c63f9 wl18xx: update firmware file 8.9.0.0.76
> > dbb85a5154a5 wl18xx: update firmware file
> > 69a250dd556b wl18xx: update firmware file
> > dbe3f134bb69 wl18xx: update firmware file, remove conf file
> > dab4b79b3fbc wl18xx: add version 4 of the wl18xx firmware
> >
> > > AND - since there's some firmware the feature doesn't work with, the
> > > driver should be fixed to detect the running firmware version and not
> > > do things that the firmware doesn't support. AND the firmware writer
> > > should also make it so the firmware doesn't barf on bad input and
> > > instead rejects it politely.
> >
> > Agreed. The main issue here seems to be that the current patch
> > assumes that this feature is available. A proper approach would
> > be to check if this feature is available before trying to use it.
> >
> > Now, I dunno if version 8.9.0.0.81 has what's required for it to
> > work - or if KEY_IGTK require some custom firmware version.
> >
> > If it works with such version, one way would be to add a check
> > for this specific version, disabling KEY_IGTK otherwise.
> >
> > Also, someone from TI should be sending the newer version to
> > be added at linux-firmware.
> >
> > I'll try to do a test maybe tomorrow.
> >
>
> I think we're totally agreed on all of the above points.
> Fundamentally: the orig patch should've been coded defensively and
> tested properly since clearly it causes certain firmwares to break.
> Be nice if TI would both update the firmware and also update the
> driver to detect the relevant version for features. I don't know
> about this one, but I do know the QCA firmwares (and others) have a
> set of feature flags that are detected by the drivers to determine
> what is supported.
>
> I look forward to hearing the results of your test. This whole thing
> has gotten me interested. I'd be tempted to pull out the relevant dev
> boards and play with them myself, but IIRC they got sent back to a
> previous employer and I don't have access to them anymore.

I upgraded to the newest firmware available at TI firmware site:

https://git.ti.com/cgit/wilink8-wlan/wl18xx_fw/log/

No joy. It worked once, but I guess it just selected some different
cipher, as the access point it is logging in is set to WPA2-PSK
with auto cipher.

I even wrote a patch that checks the version, enabling AES-CMAC
algorithm only with newer firmware (see below).

Maybe this feature will only be available on some future firmware
or it requires some custom-made one. It may also require some
newer version of the chipset.

So, for now, I suggest to revert this patch, c/c stable.

A later patch can be re-enable it, once some additional logic
gets added in order to validate if this algorithm is
properly supported by the hardware/firmware.


Thanks,
Mauro

[PATCH] net: wireless: wlcore: fix support for IGTK key

Changeset 2b7aadd3b9e1 ("wlcore: Adding suppoprt for IGTK key in wlcore driver")
added support for AEC-CMAC cipher suite.

However, this only works with the very newest firmware version
(8.9.0.0.81). Such firmware weren't even pushed to linux-firmware
git tree yet:

https://git.ti.com/cgit/wilink8-wlan/wl18xx_fw/log/

Due to that, it causes a regression betwen Kernel 5.7 and 5.8:
with such patch applied, WiFi stops working, and the Kernel starts
printing this message every second:

wlcore: PHY firmware version: Rev 8.2.0.0.242
wlcore: firmware booted (Rev 8.9.0.0.79)
wlcore: ERROR command execute failure 14
------------[ cut here ]------------
WARNING: CPU: 0 PID: 133 at drivers/net/wireless/ti/wlcore/main.c:795 wl12xx_queue_recovery_work.part.0+0x6c/0x74 [wlcore]
Modules linked in: wl18xx wlcore mac80211 libarc4 cfg80211 rfkill snd_soc_hdmi_codec crct10dif_ce wlcore_sdio adv7511 cec kirin9xx_drm(C) kirin9xx_dw_drm_dsi(C) drm_kms_helper drm ip_tables x_tables ipv6 nf_defrag_ipv6
CPU: 0 PID: 133 Comm: kworker/0:1 Tainted: G WC 5.8.0+ #186
Hardware name: HiKey970 (DT)
Workqueue: events_freezable ieee80211_restart_work [mac80211]
pstate: 60000005 (nZCv daif -PAN -UAO BTYPE=--)
pc : wl12xx_queue_recovery_work.part.0+0x6c/0x74 [wlcore]
lr : wl12xx_queue_recovery_work+0x24/0x30 [wlcore]
sp : ffff8000126c3a60
x29: ffff8000126c3a60 x28: 00000000000025de
x27: 0000000000000010 x26: 0000000000000005
x25: ffff0001a5d49e80 x24: ffff8000092cf580
x23: ffff0001b7c12623 x22: ffff0001b6fcf2e8
x21: ffff0001b7e46200 x20: 00000000fffffffb
x19: ffff0001a78e6400 x18: 0000000000000030
x17: 0000000000000001 x16: 0000000000000001
x15: ffff0001b7e46670 x14: ffffffffffffffff
x13: ffff8000926c37d7 x12: ffff8000126c37e0
x11: ffff800011e01000 x10: ffff8000120526d0
x9 : 0000000000000000 x8 : 3431206572756c69
x7 : 6166206574756365 x6 : 0000000000000c2c
x5 : 0000000000000000 x4 : ffff0001bf1361e8
x3 : ffff0001bf1790b0 x2 : 0000000000000000
x1 : ffff0001a5d49e80 x0 : 0000000000000001
Call trace:
wl12xx_queue_recovery_work.part.0+0x6c/0x74 [wlcore]
wl12xx_queue_recovery_work+0x24/0x30 [wlcore]
wl1271_cmd_set_sta_key+0x258/0x25c [wlcore]
wl1271_set_key+0x7c/0x2dc [wlcore]
wlcore_set_key+0xe4/0x360 [wlcore]
wl18xx_set_key+0x48/0x1d0 [wl18xx]
wlcore_op_set_key+0xa4/0x180 [wlcore]
ieee80211_key_enable_hw_accel+0xb0/0x2d0 [mac80211]
ieee80211_reenable_keys+0x70/0x110 [mac80211]
ieee80211_reconfig+0xa00/0xca0 [mac80211]
ieee80211_restart_work+0xc4/0xfc [mac80211]
process_one_work+0x1cc/0x350
worker_thread+0x13c/0x470
kthread+0x154/0x160
ret_from_fork+0x10/0x30
---[ end trace b1f722abf9af5919 ]---
wlcore: WARNING could not set keys
wlcore: ERROR Could not add or replace key
wlan0: failed to set key (4, ff:ff:ff:ff:ff:ff) to hardware (-5)
wlcore: Hardware recovery in progress. FW ver: Rev 8.9.0.0.79
wlcore: pc: 0x0, hint_sts: 0x00000040 count: 39
wlcore: down
wlcore: down
ieee80211 phy0: Hardware restart was requested
mmc_host mmc0: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
mmc_host mmc0: Bus speed (slot 0) = 25000000Hz (slot req 25000000Hz, actual 25000000HZ div = 0)
wlcore: PHY firmware version: Rev 8.2.0.0.242
wlcore: firmware booted (Rev 8.9.0.0.79)
wlcore: ERROR command execute failure 14
------------[ cut here ]------------

Fix it by adding some code that will check if the firmware version
is at least version 8.9.0.0.81.

Fixes: 2b7aadd3b9e1 ("wlcore: Adding suppoprt for IGTK key in wlcore driver")
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx>

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index de6c8a7589ca..db9e410c5d0b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>
+#include <linux/ctype.h>

#include "wlcore.h"
#include "debug.h"
@@ -1082,6 +1083,45 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
return ret;
}

+bool wl1271_check_aes_cmac_cypher(struct wl1271 *wl)
+{
+ int ver[5] = { };
+ int ret;
+ const char *p = wl->chip.fw_ver_str;
+
+
+ /* The string starts with "Rev ". Ignore it */
+ while (*p && !isdigit(*p))
+ p++;
+
+ ret = sscanf(p, "%d.%d.%d.%d.%d",
+ &ver[0], &ver[1], &ver[2], &ver[3], &ver[4]);
+
+ if (ret != ARRAY_SIZE(ver)) {
+ wl1271_info("Parsed version: %d.%d.%d.%d.%d\n",
+ ver[0], ver[1], ver[2], ver[3], ver[4]);
+ wl1271_error("Couldn't parse firmware version string: %d\n", ret);
+ return false;
+ }
+
+ /*
+ * Only versions equal (and probably above) 8.9.0.0.81
+ * supports such feature.
+ */
+ if (ver[0] < 8)
+ return false;
+ if (ver[1] < 9)
+ return false;
+ if (ver[2] > 0)
+ return true;
+ if (ver[3] > 0)
+ return true;
+ if (ver[4] >= 81)
+ return true;
+
+ return false;
+}
+
int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)
{
int retries = WL1271_BOOT_RETRIES;
@@ -1133,6 +1173,8 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode)
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));

+ wl->has_aes_cmac_cipher = wl1271_check_aes_cmac_cypher(wl);
+
goto out;

power_off:
@@ -2358,6 +2400,8 @@ static int wl12xx_init_fw(struct wl1271 *wl)
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));

+ wl->has_aes_cmac_cipher = wl1271_check_aes_cmac_cypher(wl);
+
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
@@ -3551,6 +3595,10 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
key_type = KEY_GEM;
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
+ if (!wl->has_aes_cmac_cipher) {
+ wl1271_error("AEC CMAC cipher not available on this firmware version\n");
+ return -EOPNOTSUPP;
+ }
key_type = KEY_IGTK;
break;
default:
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index b7821311ac75..26a2bd9b2df1 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -213,6 +213,8 @@ struct wl1271 {
void *nvs;
size_t nvs_len;

+ u32 has_aes_cmac_cipher:1;
+
s8 hw_pg_ver;

/* address read from the fuse ROM */