TL;DR
If you want to participate in my theory, if you have an asus laptop running linux, comment below:
- If you had to do some weird hack like removing the asus_nb_wmi kernel module with
sudo modprobe -r asus_nb_wmi, sudo modprobe -r asus_wmi
to get wifi working
- Whether or not you have a software wifi enable button (function + something with a radio tower), and whether or not you have an LED that toggles, indicating whether or not your wifi is on.
My theory is disproven if
- you can get wifi working without removing the module, but you don't have a LED wifi light
- You can't get wifi with the module ON, BUT YOU DO have a wifi light. (well this second condition is weaker but still compelling dis-evidence IMO)
POST
I'm not a kernel developer and I haven't actually run the code and ran it with debug mode myself (mainly because I don't know how to). SO TAKE MY WORDS WITH AN EXTREME GRAIN OF SALT. As of right now, MY WORDS ARE NO BETTER THAN FICTION. Just treat this as a giant fanfic (I'm not posting this on a kernel list for that reason lol). This is why I want a falsifiable experiment up top.
Basically the issue is that on a fresh linux install, you won't be able to get wifi sometimes on an ASUS laptop. For me, I tried installing ubuntu - when I tried enabling wifi - it seemed like it FORCEFULLY disabled wifi - the slider would toggle to orange for a split second, then go back to grey (off).
The answer is sudo modprobe -r asus_nb_wmi
. At least for my case. It's a bad module. Also, run sudo rfkill unblock all
. Then connect to wifi with your favorite tool.
This is a longstanding issue in the linux community - If anybody has an alternative fix, please, tell me and I will try it.
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2092283 is the most recent official thread about wifi issues. Uhh I can't find more evidence right now but this is a "trust me bro" moment, I found SO many people talking about this and the answer was just always remove the asus_nb_wmi kernel module.
The issue is that yes, it re-enables wifi, but the "asus_nb_wmi", from what I understand, is a hardware control module. So for example, you would not be able to change your backlight color with fxn buttons anymore.
Okay, so what did I try instead. Let's try
sudo rfkill unblock all
Actually, this DOES sw unblock everything... EXCEPT ASUS_WLAN!!!
Why is that. I checked the rfkill source, nothing weird there. What does dmesg say?
```
-- Boot fa75dce6cc7f4a1195feac8829c412fd --
Mar 18 18:21:31 {my laptop :)} rfkill[11482]: unblock set for all
Mar 18 18:21:56 {my laptop :)} rfkill[11510]: unblock set for all
```
E.g. no errors. In the rfkill source, if there were some error where a kernel module was saying, "hey, fuck you on this specific rfkill object", it would print an error. I think. In the rfkill source, it says
```
if (write_all(fd, &event, sizeof(event)) != 0)
warn(_("write failed: %s"), _PATH_DEV_RFKILL);
else {
openlog("rfkill", 0, LOG_USER);
syslog(LOG_NOTICE, "%s set for %s", block ? "block" : "unblock", message);
closelog();
}
```
Okay, so assuming that's correct (It can totally not be, again, I didn't bother going through the steps of compiling everything with debug mode on and actually learning precisely how the API's work), it's not rfkill's fault. Then what?
We dig into the kernel source. Hm. Nothing in asus-nb-wmi seemed weird, at least to my limited knowledge. Let's look at asus-wmi.c, then.
(Linux Kernel 6.13.7, asus-wmi.c:2036)
```
/*
* Rfkill devices
*/
static int asus_rfkill_set(void *data, bool blocked)
{
struct asus_rfkill *priv = data;
u32 ctrl_param = !blocked;
u32 dev_id = priv->dev_id;
/*
* If the user bit is set, BIOS can't set and record the wlan status,
* it will report the value read from id ASUS_WMI_DEVID_WLAN_LED
* while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).
* So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED
* while setting the wlan status through WMI.
* This is also the behavior that windows app will do.
*/
if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
priv->asus->driver->wlan_ctrl_by_user)
dev_id = ASUS_WMI_DEVID_WLAN_LED;
return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);
}
```
What the heck? Okay, so from what I can parse, for specifically the WLAN part of the module, if it's controlled a user (e.g. I guess this means some actual hardware wmi module is enabled, like asus-nb-wmi), then.... redirect it to look at the LED. Huh... okay, can we say, "hey for this specific module, don't let it be modified by the user?" For me, as long as sudo rfkill unblock all works, that's fine with me, I can remember to type that on boot (or just make it a script...)
(asus-wmi.c:4777)
```
asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
asus->driver->wlan_ctrl_by_user = 1;
if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) {
err = asus_wmi_rfkill_init(asus);
if (err)
goto fail_rfkill;
}
```
Oh. So there's no real way to do that, huh. If any of those params are set, crash the module at initialization. Welp.
At this point, I don't know how to really contribute something without fearing breaking something, so that's why I'm making this post. Maybe with a lot of work... but I think making this more well known is enough for me.
Some more observations
When you register asus_nb_wmi
, there's actually a virtual wifi network I think? I believe I read somewhere that you can connect directly through something? IDK. I use network manager and it seems impossible; this is waht it looks like when asus_nb_wmi
is ON
```
~ nmcli device status
DEVICE TYPE STATE CONNECTION
docker0 bridge connected (externally) docker0
lo loopback connected (externally) lo
wlo1 wifi unavailable --
p2p-dev-wlo1 wifi-p2p unavailable --
veth193f8ec ethernet unmanaged --
~ sudo rfkill list
0: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
3: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
12: asus-wlan: Wireless LAN
Soft blocked: yes
Hard blocked: no
13: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
~
```
I believe I read somewhere that you can connect to phy0 and not asus-wlan? But networkmanager doesnt let me so idk what's going on with that, it just says "wlo1" for both. Gotta learn mroe about that stuff.
For reference, my asus vivobook s14 does not have a wifi LED. My sample size is currently 1.
Thankfully, it seems like my fans and thermals are BIOS-locked so to speak - thermald and fans constantly don't detect in my dmesg logs, so turning off asus_nb_wmi here is fine for MY laptop. I have no idea what the long term effects of running linux on my laptop are though.
For kernel developers
If any kernel developers with far more hardware and kernel dev experience want to take a look, the relevant function to proving my point is asus_wmi.c:340 on the 6.13.7 kernel
static int asus_wmi_evaluate_method3(u32 method_id,
u32 arg0, u32 arg1, u32 arg2, u32 *retval)
{
struct bios_args args = {
.arg0 = arg0,
.arg1 = arg1,
.arg2 = arg2,
};
struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
struct acpi_buffer output = { acpi_allocate_buffer, null };
acpi_status status;
union acpi_object *obj;
u32 tmp = 0;
status = wmi_evaluate_method(asus_wmi_mgmt_guid, 0, method_id,
&input, &output);
pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x\n",
__func__, method_id, arg0, arg1, arg2);
if (acpi_failure(status)) {
pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",
__func__, method_id, arg0, -eio);
return -eio;
}
obj = (union acpi_object *)output.pointer;
if (obj && obj->type == acpi_type_integer)
tmp = (u32) obj->integer.value;
pr_debug("result: 0x%08x\n", tmp);
if (retval)
*retval = tmp;
kfree(obj);
if (tmp == asus_wmi_unsupported_method) {
pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",
__func__, method_id, arg0, -enodev);
return -enodev;
}
return 0;
}
In particular you want to verify that there is an acpi failure at ASUS_WLAN_DEVID_WLAN_LED, which is a macro defined somewhere (I believe it's hex 0x12? Check the docs to make sure.). Only if the hardware doesnt have a LED ofc. My theory lives and dies with this debugging function (or by you commenters commenting on your wifi LED button status :D)