Lenovo ideapad-330C installs Realtek 8821CE wireless card driver on Ubuntu 18.04

After installing Ubuntu 18.04 on the newly purchased Lenovo ideapad-330C notebook, I found sadly that there is no wireless network, fortunately, the cable can still be used. Then I searched the Internet and found that many people encountered this problem, and some people gave solutions.

Reference link: ThinkPad e470c (integrated network card rlt8111/8618/8411 Series) wireless network card rtl8821CE series installation of ubuntu and win10 dual systems without wireless network problems (invasion and deletion)

In the above link, the solution and download address of rtl8821ce source compression package of wireless network card are given. Download it if necessary.

 

System: Ubuntu 18.04.2

Kernel: Linux 4.18

Network card: Realtek 8821CE Wireless LAN 802.11ac PCI-E NIC

According to the method of reference link, the network card driver was installed successfully. In this computer, you can connect wifi without restarting, but later the system is updated... When the kernel is updated to Linux 5.0.0.31 at Ubuntu 18.04.3, it is found that there is no driver for wireless network card after restarting.

System at this time: Ubuntu 18.04.3

Kernel: Linux 5.0.0.31

I had to do it again according to the original method. I found that there was an error in the compilation and the configuration was not changed. The following error occurred in make.

rtl8821ce/os_dep/linux/os_intfs.c:1325:22: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
  .ndo_select_queue = rtw_select_queue,

Looking at this error, I don't know what happened, so I had to look it up on the Internet. I found the statement that someone said it was a type mismatch, and then I found the declaration of ndo [Select] queue in the source code of the kernel.

u16            (*ndo_select_queue)(struct net_device *dev,
                            struct sk_buff *skb,
                            struct net_device *sb_dev,
                            select_queue_fallback_t fallback);

The code rtl8821ce / OS ﹣ dep / Linux / OS ﹣ intfs. C: 1192 in the network card is like this

static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
    , void *accel_priv
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
    , select_queue_fallback_t fallback
    #endif
#endif

 

In this way, you can only modify the source code of the network card driver to adapt to the Linux 5.0 or above kernel. The code is as follows, adding the judgment of the Linux 5.0 or above kernel.

static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
    , struct net_device *sb_dev
    , select_queue_fallback_t fallback
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
    , void *accel_priv
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
    , select_queue_fallback_t fallback
    #endif
#endif

Change to save, continue to make, and report an error

rtl8821ce/os_dep/linux/rtw_android.c:629:62: error: macro "access_ok" passed 3 arguments, but takes just 2
  if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
                                                              ^
rtl8821ce/os_dep/linux/rtw_android.c:629:7: error: 'access_ok' undeclared (first use in this function)
  if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {

The method is the same as above. Continue to find the declaration of access UUK in the kernel header file. It is found that there are only two parameters of access UUK above Linux 5.0, while there are three parameters when it is used on the network card driver.

Manually modify the network card driver source code, file: rtl8821ce / OS ﹣ dep / Linux / RTW ﹣ Android. C: 629, modified as follows: (delete the original if (! Access ﹣ OK (verify ﹣ read, priv ﹣ CMD. Buf, priv ﹣ CMD. Total ﹣ len)) {this line of code, add the following code)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
    if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
#else
    if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
#endif

Save, continue to make, and report an error as follows:

rtl8821ce/os_dep/linux/ioctl_cfg80211.c: In function 'rtw_get_systime_us':
rtl8821ce/os_dep/linux/ioctl_cfg80211.c:339:2: error: implicit declaration of function 'get_monotonic_boottime'; did you mean 'getboottime'? [-Werror=implicit-function-declaration]
  get_monotonic_boottime(&ts);
  ^~~~~~~~~~~~~~~~~~~~~~
  getboottime

Here is a hint for modification. However, we can't find the function get monotonic boottime in the same way, but we can find the function getboottime for hint. Replace it with the following one. Considering the kernel version lower than 5.0, we will add a judgment.

As above, delete the line rtl8821ce / OS ﹣ dep / Linux / IOCTL ﹣ cfg80211. C: 339, and add the following code

    #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
        getboottime(&ts);
    #else
        get_monotonic_boottime(&ts);
    #endif

This time make finally succeeded!

make
sudo make install
sudo modprobe -a 8821ce

This computer can connect to the original wifi without rebooting

A few days later, the computer was updated again. After restarting, it was found that there was no wireless card driver. After a look, the original kernel was upgraded again. This time:

System: Ubuntu 18.04.3

Kernel: Linux 5.0.0.32

A small change to the kernel has eliminated the original network card driver. Fortunately, the source code change of the last network card driver is still in progress. Repeat the following operations.

make
sudo make install
sudo modprobe -a 8821ce

Ha ha, it's OK again

Keywords: Linux network Ubuntu sudo

Added by artiemus on Tue, 29 Oct 2019 14:40:56 +0200