Commit 857fe9e5 authored by Pavel Skripkin's avatar Pavel Skripkin Committed by Greg Kroah-Hartman
Browse files

staging: r8188eu: add error handling of rtw_read8



rtw_read8() reads data from device via USB API which may fail. In case
of any failure previous code returned stack data to callers, which is
wrong.

Fix it by changing rtw_read8() prototype and prevent caller from
touching random stack data

Signed-off-by: default avatarPavel Skripkin <paskripkin@gmail.com>
Link: https://lore.kernel.org/r/c8f8ef4f14db3ba2478a87d5be6eb768a093dfaf.1654629778.git.paskripkin@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent da30e351
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -28,14 +28,21 @@ ReadEFuseByte(
	u32 value32;
	u8 readbyte;
	u16 retry;
	int res;

	/* Write Address */
	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
	res = rtw_read8(Adapter, EFUSE_CTRL + 2, &readbyte);
	if (res)
		return;

	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));

	/* Write bit 32 0 */
	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
	res = rtw_read8(Adapter, EFUSE_CTRL + 3, &readbyte);
	if (res)
		return;

	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));

	/* Check bit 32 read-ready */
@@ -54,6 +61,8 @@ ReadEFuseByte(
	value32 = rtw_read32(Adapter, EFUSE_CTRL);

	*pbuf = (u8)(value32 & 0xff);

	/* FIXME: return an error to caller */
}

/*-----------------------------------------------------------------------------
+43 −13
Original line number Diff line number Diff line
@@ -44,18 +44,28 @@ static_assert(sizeof(struct rt_firmware_hdr) == 32);
static void fw_download_enable(struct adapter *padapter, bool enable)
{
	u8 tmp;
	int res;

	if (enable) {
		/*  MCU firmware download enable. */
		tmp = rtw_read8(padapter, REG_MCUFWDL);
		res = rtw_read8(padapter, REG_MCUFWDL, &tmp);
		if (res)
			return;

		rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);

		/*  8051 reset */
		tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
		res = rtw_read8(padapter, REG_MCUFWDL + 2, &tmp);
		if (res)
			return;

		rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
	} else {
		/*  MCU firmware download disable. */
		tmp = rtw_read8(padapter, REG_MCUFWDL);
		res = rtw_read8(padapter, REG_MCUFWDL, &tmp);
		if (res)
			return;

		rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);

		/*  Reserved for fw extension. */
@@ -125,8 +135,13 @@ static int page_write(struct adapter *padapter, u32 page, u8 *buffer, u32 size)
{
	u8 value8;
	u8 u8Page = (u8)(page & 0x07);
	int res;

	res = rtw_read8(padapter, REG_MCUFWDL + 2, &value8);
	if (res)
		return _FAIL;

	value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
	value8 = (value8 & 0xF8) | u8Page;
	rtw_write8(padapter, REG_MCUFWDL + 2, value8);

	return block_write(padapter, buffer, size);
@@ -165,8 +180,12 @@ static int write_fw(struct adapter *padapter, u8 *buffer, u32 size)
void rtw_reset_8051(struct adapter *padapter)
{
	u8 val8;
	int res;

	res = rtw_read8(padapter, REG_SYS_FUNC_EN + 1, &val8);
	if (res)
		return;

	val8 = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
	rtw_write8(padapter, REG_SYS_FUNC_EN + 1, val8 & (~BIT(2)));
	rtw_write8(padapter, REG_SYS_FUNC_EN + 1, val8 | (BIT(2)));
}
@@ -239,7 +258,7 @@ static int load_firmware(struct rt_firmware *rtfw, struct device *device)
int rtl8188e_firmware_download(struct adapter *padapter)
{
	int ret = _SUCCESS;
	u8 write_fw_retry = 0;
	u8 reg;
	unsigned long fwdl_timeout;
	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
	struct device *device = dvobj_to_dev(dvobj);
@@ -269,23 +288,34 @@ int rtl8188e_firmware_download(struct adapter *padapter)

	/*  Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
	/*  or it will cause download Fw fail. 2010.02.01. by tynli. */
	if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
	ret = rtw_read8(padapter, REG_MCUFWDL, &reg);
	if (ret) {
		ret = _FAIL;
		goto exit;
	}

	if (reg & RAM_DL_SEL) { /* 8051 RAM code */
		rtw_write8(padapter, REG_MCUFWDL, 0x00);
		rtw_reset_8051(padapter);
	}

	fw_download_enable(padapter, true);
	fwdl_timeout = jiffies + msecs_to_jiffies(500);
	while (1) {
	do {
		/* reset the FWDL chksum */
		rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL) | FWDL_CHKSUM_RPT);
		ret = rtw_read8(padapter, REG_MCUFWDL, &reg);
		if (ret) {
			ret = _FAIL;
			continue;
		}

		ret = write_fw(padapter, fw_data, fw_size);
		rtw_write8(padapter, REG_MCUFWDL, reg | FWDL_CHKSUM_RPT);

		if (ret == _SUCCESS ||
		    (time_after(jiffies, fwdl_timeout) && write_fw_retry++ >= 3))
		ret = write_fw(padapter, fw_data, fw_size);
		if (ret == _SUCCESS)
			break;
	}
	} while (!time_after(jiffies, fwdl_timeout));

	fw_download_enable(padapter, false);
	if (ret != _SUCCESS)
		goto exit;
+13 −3
Original line number Diff line number Diff line
@@ -35,11 +35,15 @@ static void ResetLedStatus(struct LED_871x *pLed)
static void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
{
	u8	LedCfg;
	int res;

	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
		return;

	LedCfg = rtw_read8(padapter, REG_LEDCFG2);
	res = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);
	if (res)
		return;

	rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /*  SW control led0 on. */
	pLed->bLedOn = true;
}
@@ -47,15 +51,21 @@ static void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
static void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
{
	u8	LedCfg;
	int res;

	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
		goto exit;

	LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
	res = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);/* 0x4E */
	if (res)
		goto exit;

	LedCfg &= 0x90; /*  Set to software control. */
	rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
	LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
	res = rtw_read8(padapter, REG_MAC_PINMUX_CFG, &LedCfg);
	if (res)
		goto exit;

	LedCfg &= 0xFE;
	rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
exit:
+40 −8
Original line number Diff line number Diff line
@@ -5650,14 +5650,28 @@ unsigned int send_beacon(struct adapter *padapter)

bool get_beacon_valid_bit(struct adapter *adapter)
{
	int res;
	u8 reg;

	res = rtw_read8(adapter, REG_TDECTRL + 2, &reg);
	if (res)
		return false;

	/* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2 */
	return BIT(0) & rtw_read8(adapter, REG_TDECTRL + 2);
	return BIT(0) & reg;
}

void clear_beacon_valid_bit(struct adapter *adapter)
{
	int res;
	u8 reg;

	res = rtw_read8(adapter, REG_TDECTRL + 2, &reg);
	if (res)
		return;

	/* BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
	rtw_write8(adapter, REG_TDECTRL + 2, rtw_read8(adapter, REG_TDECTRL + 2) | BIT(0));
	rtw_write8(adapter, REG_TDECTRL + 2, reg | BIT(0));
}

/****************************************************************************
@@ -5985,7 +5999,8 @@ static void rtw_set_bssid(struct adapter *adapter, u8 *bssid)
static void mlme_join(struct adapter *adapter, int type)
{
	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
	u8 retry_limit = 0x30;
	u8 retry_limit = 0x30, reg;
	int res;

	switch (type) {
	case 0:
@@ -6010,7 +6025,11 @@ static void mlme_join(struct adapter *adapter, int type)
	case 2:
		/* sta add event call back */
		/* enable update TSF */
		rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) & (~BIT(4)));
		res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
		if (res)
			return;

		rtw_write8(adapter, REG_BCN_CTRL, reg & (~BIT(4)));

		if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
			retry_limit = 0x7;
@@ -6731,6 +6750,9 @@ void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *p

static void mlme_disconnect(struct adapter *adapter)
{
	int res;
	u8 reg;

	/* Set RCR to not to receive data frame when NO LINK state */
	/* reject all data frames */
	rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
@@ -6739,7 +6761,12 @@ static void mlme_disconnect(struct adapter *adapter)
	rtw_write8(adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));

	/* disable update TSF */
	rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) | BIT(4));

	res = rtw_read8(adapter, REG_BCN_CTRL, &reg);
	if (res)
		return;

	rtw_write8(adapter, REG_BCN_CTRL, reg | BIT(4));
}

void mlmeext_sta_del_event_callback(struct adapter *padapter)
@@ -6793,14 +6820,15 @@ static u8 chk_ap_is_alive(struct sta_info *psta)
	return ret;
}

static void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
static int rtl8188e_sreset_linked_status_check(struct adapter *padapter)
{
	u32 rx_dma_status =  rtw_read32(padapter, REG_RXDMA_STATUS);
	u8 reg;

	if (rx_dma_status != 0x00)
		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);

	rtw_read8(padapter, REG_FMETHR);
	return rtw_read8(padapter, REG_FMETHR, &reg);
}

void linked_status_chk(struct adapter *padapter)
@@ -7202,6 +7230,7 @@ u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
	struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
	u8 val8;
	int res;

	if (is_client_associated_to_ap(padapter))
		issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);
@@ -7214,7 +7243,10 @@ u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)

	if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
		/* Stop BCN */
		val8 = rtw_read8(padapter, REG_BCN_CTRL);
		res = rtw_read8(padapter, REG_BCN_CTRL, &val8);
		if (res)
			return H2C_DROPPED;

		rtw_write8(padapter, REG_BCN_CTRL, val8 & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
	}

+17 −3
Original line number Diff line number Diff line
@@ -279,8 +279,13 @@ void Restore_DM_Func_Flag(struct adapter *padapter)
void Set_MSR(struct adapter *padapter, u8 type)
{
	u8 val8;
	int res;

	val8 = rtw_read8(padapter, MSR) & 0x0c;
	res = rtw_read8(padapter, MSR, &val8);
	if (res)
		return;

	val8 &= 0x0c;
	val8 |= type;
	rtw_write8(padapter, MSR, val8);
}
@@ -505,7 +510,11 @@ int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)

static void set_acm_ctrl(struct adapter *adapter, u8 acm_mask)
{
	u8 acmctrl = rtw_read8(adapter, REG_ACMHWCTRL);
	u8 acmctrl;
	int res = rtw_read8(adapter, REG_ACMHWCTRL, &acmctrl);

	if (res)
		return;

	if (acm_mask > 1)
		acmctrl = acmctrl | 0x1;
@@ -765,6 +774,7 @@ void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
static void set_min_ampdu_spacing(struct adapter *adapter, u8 spacing)
{
	u8 sec_spacing;
	int res;

	if (spacing <= 7) {
		switch (adapter->securitypriv.dot11PrivacyAlgrthm) {
@@ -786,8 +796,12 @@ static void set_min_ampdu_spacing(struct adapter *adapter, u8 spacing)
		if (spacing < sec_spacing)
			spacing = sec_spacing;

		res = rtw_read8(adapter, REG_AMPDU_MIN_SPACE, &sec_spacing);
		if (res)
			return;

		rtw_write8(adapter, REG_AMPDU_MIN_SPACE,
			   (rtw_read8(adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | spacing);
			   (sec_spacing & 0xf8) | spacing);
	}
}

Loading