Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stopped working with NetworkManager since kernel 4.4.74 #30

Open
PVince81 opened this issue Jul 27, 2017 · 5 comments
Open

Stopped working with NetworkManager since kernel 4.4.74 #30

PVince81 opened this issue Jul 27, 2017 · 5 comments

Comments

@PVince81
Copy link
Contributor

See more detailed report here: https://bugzilla.suse.com/show_bug.cgi?id=1050959

Basically the driver stopped working with NetworkManager since kernel 4.4.75.
It still works if I boot kernel 4.4.62.

And also wpa_supplicant itself works, and if wpa_supplicant runs before NetworkManager is started, then NetworkManager works too. It seems that the driver/device needs to be set into a specific state for NetworkManager to work.

Not sure if it's an issue with the driver which needs adjusting for newer kernel or just a but in NetworkManager.

This is a diff of the NetworkManager log. Left is when it fails when run alone. Right is when wpa_supplicant was running.

< <warn>  (ra0): error 100 getting card mode
---
> <info>  (ra0): new 802.11 WiFi device (carrier: UNKNOWN, driver: 'usb', ifindex: 4)
> <info>  (ra0): device state change: unmanaged -> unavailable (reason 'managed') [10 20 2]

So maybe something wrong with the driver function that retrieves the card mode with newer kernels ?

@chenhaiq

@PVince81
Copy link
Contributor Author

PVince81 commented Aug 17, 2017

I discovered some more clues: it seems to be related to the driver's "Mode" which is always on "Auto" at the beginning. This seems to disturb NetworkManager.

When running wpa_supplicant, it will somehow switch the mode to "Managed" internally.

I tried setting the mode to "Managed" manually but "iwconfig ra0 mode Managed" doesn't switch it.

Then I patched the code to lie about the mode in giwmode:

diff --git a/os/linux/sta_ioctl.c b/os/linux/sta_ioctl.c
index 50afb88..7d4165f 100644
--- a/os/linux/sta_ioctl.c
+++ b/os/linux/sta_ioctl.c
@@ -284,7 +284,8 @@ int rt_ioctl_giwmode(struct net_device *dev,
                *mode = IW_MODE_MONITOR;
 #endif /* LINUX_VERSION_CODE */
        else
-               *mode = IW_MODE_AUTO;
+               //*mode = IW_MODE_AUTO;
+               *mode = IW_MODE_INFRA;
 
        DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode));
        return 0;

At this point, the following makes networkmanager work:

# modprobe mt7650u_sta
# ifconfig ra0 up   # for some reason it needs to be up to be picked up
# systemctl restart network   # force restart of network manager

At this state the connection works.

@PVince81
Copy link
Contributor Author

I suspect that there are three potential bugs involved:

  1. Setting mode doesn't work
  2. Returned mode is "Auto" instead of "Managed" by default ? Either driver bug or NetworkManager bug: https://bugzilla.opensuse.org/show_bug.cgi?id=1050959
  3. Driver reports "network is down" by default. It looks like it's not supposed to and should be up but unconnected by default. Could be a requirement/behavior from the newer kernels.

@PVince81
Copy link
Contributor Author

Okay, first I tried to write a udev rule to automatically run ifconfig ra0 up and restart network managed, but it didn't work at boot time.

Then I noticed in the network manager log that when it starts it does find ra0 but fails with "error 100 getting card mode".

I have the feeling that since Kernel 4.4.75+ something has changed in the order how network device APIs are called.

Here is the fix that works for me: return "Managed" even if the "network is down":

diff --git a/os/linux/sta_ioctl.c b/os/linux/sta_ioctl.c
index 50afb88..57bc046 100644
--- a/os/linux/sta_ioctl.c
+++ b/os/linux/sta_ioctl.c
@@ -268,7 +268,10 @@ int rt_ioctl_giwmode(struct net_device *dev,
        if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS)
     {
         DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
-        return -ENETDOWN;   
+               // lie
+               *mode = IW_MODE_INFRA;
+               return 0;
+        //return -ENETDOWN;   
     }
 
 
@@ -284,7 +287,8 @@ int rt_ioctl_giwmode(struct net_device *dev,
                *mode = IW_MODE_MONITOR;
 #endif /* LINUX_VERSION_CODE */
        else
-               *mode = IW_MODE_AUTO;
+               //*mode = IW_MODE_AUTO;
+               *mode = IW_MODE_INFRA;
 
        DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode));
        return 0;

This patch applied onto master makes the wifi stick work correctly for me.

@PVince81
Copy link
Contributor Author

and I narrowed it down and removed the second hack.

So this is the minimal patch required to make the wifi stick work again for me:

diff --git a/os/linux/sta_ioctl.c b/os/linux/sta_ioctl.c
index 50afb88..18f7eca 100644
--- a/os/linux/sta_ioctl.c
+++ b/os/linux/sta_ioctl.c
@@ -268,7 +268,10 @@ int rt_ioctl_giwmode(struct net_device *dev,
        if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS)
     {
         DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
-        return -ENETDOWN;   
+               // callers like NetworkManager expect to be able to read a valid mode
+               // even when down
+        *mode = IW_MODE_INFRA;
+        return 0;
     }

@chenhaiq if interested I can submit this as PR, if the approach is valid.

@chenhaiq
Copy link
Owner

Please submit it as PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants