RK3399 偶现无法打开WIFI问题

RTL8821CS

Posted by LXG on August 19, 2024

[RK3399 Android7.1.2]新增wifi&bt模块:rtl8822cs驱动以及解决所遇问题

问题步骤

  1. 连接WIFI
  2. 循环软重启设备
  3. 偶现某次重启后无法打开WIFI
  4. lsmod 没有wifi模组ko驱动

问题日志

正常日志


[    3.841058] mmc_host mmc2: Bus speed (slot 0) = 100000000Hz (slot req 100000000Hz, actual 100000000HZ div = 0)

[    4.388154] dwmmc_rockchip fe310000.dwmmc: Successfully tuned phase to 206

[    4.391066] mmc2: new ultra high speed SDR50 SDIO card at address 0001

[   13.786083] RTW: module init start
[   13.786173] RTW: rtl8821cs v5.12.0-8-g39bbb8dd2.20201015_COEX20200730-5151
[   13.786363] RTW: build time: Aug 17 2024 14:07:56
[   13.786604] RTW: rtl8821cs BT-Coex version = COEX20200730-5151

异常日志


[    3.804439] mmc2: Skipping voltage switch
[    5.138046] mmc2: error -110 whilst initialising SDIO card
[    5.637970] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)
[    5.651471] mmc_host mmc2: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
[    5.672029] dwmmc_rockchip fe310000.dwmmc: card claims to support voltages below defined range

[    5.704434] mmc2: Skipping voltage switch
[    7.077991] mmc2: error -110 whilst initialising SDIO card
[    7.577963] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)
[    7.591382] mmc_host mmc2: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
[    7.617742] dwmmc_rockchip fe310000.dwmmc: card claims to support voltages below defined range

[    7.651318] mmc2: Skipping voltage switch
[    9.001339] mmc2: error -110 whilst initialising SDIO card
[    9.501289] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)

驱动源码

kernel/drivers/mmc/core/sdio.c


/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
			      struct mmc_card *oldcard, int powered_resume)
{
	struct mmc_card *card;
	int err;
	int retries = 10;
	u32 rocr = 0;
	u32 ocr_card = ocr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/* to query card if 1.8V signalling is supported */
	if (mmc_host_uhs(host))
		ocr |= R4_18V_PRESENT;

try_again:
	if (!retries) {
	        // 此处打印
		pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host));
		ocr &= ~R4_18V_PRESENT;
	}

        //----------------------------省略代码-----------------------------

	/* If the host and card support UHS-I mode request the card
	 * to switch to 1.8V signaling level.  No 1.8v signalling if
	 * UHS mode is not enabled to maintain compatibility and some
	 * systems that claim 1.8v signalling in fact do not support
	 * it. Per SDIO spec v3, section 3.1.2, if the voltage is already
	 * 1.8v, the card sets S18A to 0 in the R4 response. So it will
	 * fails to check rocr & R4_18V_PRESENT,  but we still need to
	 * try to init uhs card. sdio_read_cccr will take over this task
	 * to make sure which speed mode should work.
	 */
	if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
		err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
					ocr_card);
		if (err == -EAGAIN) {
			mmc_sdio_resend_if_cond(host, card);
			retries--;
			goto try_again;
		} else if (err) {
			ocr &= ~R4_18V_PRESENT;
		}
	}

        //------------------------------省略代码----------------------------
}

修改方案

Realtek 88x2BS系列, SDIO 3.0是1.8V,原先代码是走到一个函数里设置信号电压为1.8V,正常就可继续流程 错误返回I/O error ;所以要跳过设置信号电压这个步骤即可

kernel/drivers/mmc/core/sdio.c


	if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
	        // modify start
	        // https://www.codeleading.com/article/96705503300/
		// err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
		// 			ocr_card);
		pr_warn("%s: Skip set signal voltage to 1.8v\n", mmc_hostname(host));
		err = 0;
		// modify end
		if (err == -EAGAIN) {
			mmc_sdio_resend_if_cond(host, card);
			retries--;
			goto try_again;
		} else if (err) {
			ocr &= ~R4_18V_PRESENT;
		}
	}