Skip to contentSkip to conversation

staging: r8188eu: avoid uninit value bugs

RFC PATCH Superseded Pavel Skripkin 10 participants 120 messages Aug 20, 2021 – Aug 30, 2021 Staging

lore
Share & tools
lore
#0 lore raw

cover staging: r8188eu: avoid uninit value bugs

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've expanded read() API with error parametr, which will be initialized to error if read fails. It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

This series was build-tested and made on top of staging-testing branch

With regards,
Pavel Skripkin

Pavel Skripkin (3):
staging: r8188eu: add proper rtw_read* error handling
staging: r8188eu: add error handling to ReadFuse
staging: r8188eu: add error argument to read_macreg

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 119 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  18 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  38 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  22 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 260 ++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 412 ++++++++++++++----
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  55 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   4 +-
 26 files changed, 1072 insertions(+), 301 deletions(-)
Signature · 1 line
2.32.0
#1 lore raw

RFC PATCH 1/3 staging: r8188eu: add proper rtw_read* error handling

rtw_read*() functions call usb_read* inside. These functions could fail in some cases; for example: failed to receive control message. These cases should be handled to prevent uninit value bugs, since usb_read* functions blindly return stack variable without checking if this value _actualy_ initialized.

To achive it, all usb_read* and rtw_read*() argument list is expanded with pointer to error and added error usbctrl_vendorreq() error checking. If transfer is successful error will be initialized to 0 otherwise to error returned from usb_control_msg().

To not break the build, added error checking for rtw_read*() call all across the driver.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      |  83 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  18 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  37 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  22 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 198 +++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 394 ++++++++++++++----
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  16 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++---
 20 files changed, 941 insertions(+), 252 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +69 -10
index 2ee64cef73f7..9f8df3cf3070 100644
@@ -73,8 +73,9 @@ int proc_get_read_reg(char *page, char **start,
 {
 	struct net_device *dev = data;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
+	int error;
 	int len = 0;
+	u32 tmp;
 
 	if (proc_get_read_addr == 0xeeeeeeee) {
 		*eof = 1;
@@ -83,19 +84,35 @@ int proc_get_read_reg(char *page, char **start,
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		tmp = rtw_read8(padapter, proc_get_read_addr, &error);
+
+		if (error)
+			goto end;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		tmp = rtw_read16(padapter, proc_get_read_addr, &error);
+
+		if (error)
+			goto end;
+
+		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
-		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+		tmp = rtw_read32(padapter, proc_get_read_addr, &error);
+
+		if (error)
+			goto end;
+
+		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, tmp);
 		break;
 	default:
 		len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
 		break;
 	}
 
+end:
 	*eof = 1;
 	return len;
 }
@@ -305,13 +322,20 @@ int proc_get_mac_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x0; i < 0x300; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+	
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -328,13 +352,20 @@ int proc_get_mac_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 	memset(page, 0, count);
 	for (i = 0x300; i < 0x600; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+	
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -351,13 +382,20 @@ int proc_get_mac_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x600; i < 0x800; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -374,12 +412,19 @@ int proc_get_bb_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0x800; i < 0xB00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -395,12 +440,19 @@ int proc_get_bb_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xB00; i < 0xE00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -416,12 +468,19 @@ int proc_get_bb_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xE00; i < 0x1000; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+		
+		tmp = rtw_read32(padapter, i, &error);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
drivers/staging/r8188eu/core/rtw_efuse.c +68 -15

173 lines not on this page · raw message

drivers/staging/r8188eu/core/rtw_io.c +9 -9
index cde0205816b1..d9684aa144c8 100644
@@ -34,44 +34,44 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
+u8 _rtw_read8(struct adapter *adapter, u32 addr, int *error)
 {
 	u8 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl *pintfhdl = &pio_priv->intf;
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 
 	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
+	r_val = _read8(pintfhdl, addr, error);
 
 	return r_val;
 }
 
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+u16 _rtw_read16(struct adapter *adapter, u32 addr, int *error)
 {
 	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read16 = pintfhdl->io_ops._read16;
 
-	r_val = _read16(pintfhdl, addr);
+	r_val = _read16(pintfhdl, addr, error);
 
 	return r_val;
 }
 
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
+u32 _rtw_read32(struct adapter *adapter, u32 addr, int *error)
 {
 	u32 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read32 = pintfhdl->io_ops._read32;
 
-	r_val = _read32(pintfhdl, addr);
+	r_val = _read32(pintfhdl, addr, error);
 
 	return r_val;
 }
drivers/staging/r8188eu/core/rtw_mp.c +29 -8
index 93bb683b628f..601a1fd5d4e7 100644
@@ -10,16 +10,17 @@
 u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
 {
 	u32 val = 0;
+	int error;
 
 	switch (sz) {
 	case 1:
-		val = rtw_read8(padapter, addr);
+		val = rtw_read8(padapter, addr, &error);
 		break;
 	case 2:
-		val = rtw_read16(padapter, addr);
+		val = rtw_read16(padapter, addr, &error);
 		break;
 	case 4:
-		val = rtw_read32(padapter, addr);
+		val = rtw_read32(padapter, addr, &error);
 		break;
 	default:
 		val = 0xffffffff;
@@ -282,10 +283,14 @@ void GetPowerTracking(struct adapter *padapter, u8 *enable)
 static void disable_dm(struct adapter *padapter)
 {
 	u8 v8;
+	int error;
 
 	/* 3 1. disable firmware dynamic mechanism */
 	/*  disable Power Training, Rate Adaptive */
-	v8 = rtw_read8(padapter, REG_BCN_CTRL);
+	v8 = rtw_read8(padapter, REG_BCN_CTRL, &error);
+	if (error)
+		return;
+
 	v8 &= ~EN_BCN_FUNCTION;
 	rtw_write8(padapter, REG_BCN_CTRL, v8);
 
@@ -310,6 +315,7 @@ s32 mp_start_test(struct adapter *padapter)
 	struct mp_priv *pmppriv = &padapter->mppriv;
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+	int error;
 
 	padapter->registrypriv.mp_mode = 1;
 	pmppriv->bSetTxPower = 0;		/* for  manually set tx power */
@@ -403,7 +409,11 @@ s32 mp_start_test(struct adapter *padapter)
 
 	if (res == _SUCCESS) {
 		/*  set MSR to WIFI_FW_ADHOC_STATE */
-		val8 = rtw_read8(padapter, MSR) & 0xFC; /*  0x0102 */
+		val8 = rtw_read8(padapter, MSR, &error);
+		if (error)
+			return _FAIL;
+
+		val8 &= 0xFC; /*  0x0102 */
 		val8 |= WIFI_FW_ADHOC_STATE;
 		rtw_write8(padapter, MSR, val8); /*  Link in ad hoc network */
 	}
@@ -795,12 +805,17 @@ static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
 {
 	/* selection */
 	u32 phyrx_set = 0, count = 0;
+	int error;
 
 	phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
 	rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
 
 	/* Read packet count */
-	count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
+	count = rtw_read32(pAdapter, REG_RXERR_RPT, &error);
+	if (error)
+		return 0;
+
+	count &= RXERR_COUNTER_MASK;
 
 	return count;
 }
@@ -833,8 +848,12 @@ u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
 static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 {
 	int psd_val;
+	int error;
+
+	psd_val = rtw_read32(pAdapter, 0x808, &error);
+	if (error)
+		return error;
 
-	psd_val = rtw_read32(pAdapter, 0x808);
 	psd_val &= 0xFFBFFC00;
 	psd_val |= point;
 
@@ -844,7 +863,9 @@ static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 
 	rtw_write32(pAdapter, 0x808, psd_val);
 	mdelay(1);
-	psd_val = rtw_read32(pAdapter, 0x8B4);
+	psd_val = rtw_read32(pAdapter, 0x8B4, &error);
+	if (error)
+		return error;
 
 	psd_val &= 0x0000FFFF;
 
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +16 -4
index c85f8e467337..ad004b176f94 100644
@@ -629,9 +629,10 @@ int rtl8188eu_oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv)
 int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 {
 	struct mp_rw_reg *RegRWStruct;
-	u32		offset, width;
+	u32		offset, width, tmp;
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+	int error;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -647,17 +648,28 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 
 	switch (width) {
 	case 1:
-		RegRWStruct->value = rtw_read8(Adapter, offset);
+		tmp = rtw_read8(Adapter, offset, &error);
+		if (error)
+			return NDIS_STATUS_FAILURE;
+
 		break;
 	case 2:
-		RegRWStruct->value = rtw_read16(Adapter, offset);
+		tmp = rtw_read16(Adapter, offset, &error);
+		if (error)
+			return NDIS_STATUS_FAILURE;
+
 		break;
 	default:
 		width = 4;
-		RegRWStruct->value = rtw_read32(Adapter, offset);
+		tmp = rtw_read32(Adapter, offset, &error);
+		if (error)
+			return NDIS_STATUS_FAILURE;
+
 		break;
 	}
 
+	RegRWStruct->value = tmp;
+
 	_irqlevel_changed_(&oldirql, RAISE);
 
 	*poid_par_priv->bytes_rw = width;
drivers/staging/r8188eu/core/rtw_pwrctrl.c +5 -1
index c3897b29121c..f4accd0b01d8 100644
@@ -55,6 +55,8 @@ int ips_leave(struct adapter *padapter)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	int result = _SUCCESS;
 	int keyid;
+	u32 tmp;
+	int error;
 
 	_enter_pwrlock(&pwrpriv->lock);
 
@@ -83,7 +85,9 @@ int ips_leave(struct adapter *padapter)
 			}
 		}
 
-		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
+		tmp = rtw_read32(padapter, 0x4c, &error);
+		if (!error)
+			DBG_88E("==> ips_leave.....LED(0x%08x)...\n", tmp);
 		pwrpriv->bips_processing = false;
 
 		pwrpriv->bkeepfwalive = false;
drivers/staging/r8188eu/core/rtw_sreset.c +5 -2
index 8e1bc62e74e5..1ac3f5c6bdec 100644
@@ -29,13 +29,16 @@ u8 sreset_get_wifi_status(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	u8 status = WIFI_STATUS_SUCCESS;
 	u32 val32 = 0;
 
 	if (psrtpriv->silent_reset_inprogress)
 		return status;
-	val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
+	val32 = rtw_read32(padapter, REG_TXDMA_STATUS, &error);
+	if (error)
+		return WIFI_MAC_TXDMA_ERROR;
+
 	if (val32 == 0xeaeaeaea) {
 		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
 	} else if (val32 != 0) {
drivers/staging/r8188eu/hal/HalPwrSeqCmd.c +7 -2
index 0fd11aca7ac7..ed24d904e3f6 100644
@@ -35,6 +35,7 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 	u32 offset = 0;
 	u32 poll_count = 0; /*  polling autoload done. */
 	u32 max_poll_count = 5000;
+	int error;
 
 	do {
 		pwrcfgcmd = pwrseqcmd[aryidx];
@@ -48,7 +49,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 
 				/*  Read the value from system register */
-				value = rtw_read8(padapter, offset);
+				value = rtw_read8(padapter, offset, &error);
+				if (error)
+					return false;
 
 				value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
 				value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
@@ -60,7 +63,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				poll_bit = false;
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 				do {
-					value = rtw_read8(padapter, offset);
+					value = rtw_read8(padapter, offset, &error);
+					if (error)
+						return false;
 
 					value &= GET_PWR_CFG_MASK(pwrcfgcmd);
 					if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
drivers/staging/r8188eu/hal/hal_com.c +16 -6
index f09d4d49b159..b6cbbf2275c3 100644
@@ -319,13 +319,15 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 {
 	s32 ret = _FAIL;
 	struct c2h_evt_hdr *c2h_evt;
-	int i;
+	int i, error;
 	u8 trigger;
 
 	if (!buf)
 		goto exit;
 
-	trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
+	trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR, &error);
+	if (error)
+		goto exit;
 
 	if (trigger == C2H_EVT_HOST_CLOSE)
 		goto exit; /* Not ready */
@@ -336,13 +338,21 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 
 	memset(c2h_evt, 0, 16);
 
-	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
-	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
+	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, &error);
+	if (error)
+		goto clear_evt;
+
+	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, &error);
+	if (error)
+		;
 
 	/* Read the content */
-	for (i = 0; i < c2h_evt->plen; i++)
+	for (i = 0; i < c2h_evt->plen; i++) {
 		c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
-						sizeof(*c2h_evt) + i);
+						sizeof(*c2h_evt) + i, &error);
+		if (error)
+			goto clear_evt;
+	}
 
 	ret = _SUCCESS;
 
drivers/staging/r8188eu/hal/odm_interface.c +9 -3
index 5a01495d74bc..cedc68152401 100644
@@ -7,19 +7,25 @@
 u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read8(Adapter, RegAddr);
+	int error;
+
+	return rtw_read8(Adapter, RegAddr, &error);
 }
 
 u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read16(Adapter, RegAddr);
+	int error;
+
+	return rtw_read16(Adapter, RegAddr, &error);
 }
 
 u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read32(Adapter, RegAddr);
+	int error;
+
+	return rtw_read32(Adapter, RegAddr, &error);
 }
 
 void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
drivers/staging/r8188eu/hal/rtl8188e_cmd.c +31 -6
index 3e1a45030bc8..4447fa8de275 100644
@@ -21,11 +21,15 @@ static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
 {
 	u8 read_down = false;
 	int	retry_cnts = 100;
-
+	int error;
 	u8 valid;
 
 	do {
-		valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
+		valid = rtw_read8(adapt, REG_HMETFR, &error);
+		if (error)
+			continue;
+
+		valid &= BIT(msgbox_num);
 		if (0 == valid)
 			read_down = true;
 	} while ((!read_down) && (retry_cnts--));
@@ -580,6 +584,8 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 	bool	bcn_valid = false;
 	u8 DLBcnCount = 0;
 	u32 poll = 0;
+	u8 tmp;
+	int error;
 
 	DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
 
@@ -596,8 +602,17 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  Disable Hw protection for a time which revserd for Hw sending beacon. */
 		/*  Fix download reserved page packet fail that access collision with the protection time. */
 		/*  2010.05.11. Added by tynli. */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(3)));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(4));
+		tmp = rtw_read8(adapt, REG_BCN_CTRL, &error);
+		if (error)
+			return;
+
+		rtw_write8(adapt, REG_BCN_CTRL, tmp & (~BIT(3)));
+
+		tmp = rtw_read8(adapt, REG_BCN_CTRL, &error);
+		if (error)
+			return;
+
+		rtw_write8(adapt, REG_BCN_CTRL, tmp | BIT(4));
 
 		if (haldata->RegFwHwTxQCtrl & BIT(6)) {
 			DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
@@ -639,8 +654,18 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  */
 
 		/*  Enable Bcn */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(3));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(4)));
+
+		tmp = rtw_read8(adapt, REG_BCN_CTRL, &error);
+		if (error)
+			return;
+
+		rtw_write8(adapt, REG_BCN_CTRL, tmp | BIT(3));
+
+		tmp = rtw_read8(adapt, REG_BCN_CTRL, &error);
+		if (error)
+			return;
+
+		rtw_write8(adapt, REG_BCN_CTRL, tmp & (~BIT(4)));
 
 		/*  To make sure that if there exists an adapter which would like to send beacon. */
 		/*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
drivers/staging/r8188eu/hal/rtl8188e_dm.c +5 -1
index 78552303c990..c645d7fc8e8b 100644
@@ -16,8 +16,12 @@ static void dm_CheckStatistics(struct adapter *Adapter)
 static void dm_InitGPIOSetting(struct adapter *Adapter)
 {
 	u8	tmp1byte;
+	int error;
+
+	tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG, &error);
+	if (error)
+		return;
 
-	tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
 	tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
 
 	rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +159 -39

407 lines not on this page · raw message

drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +21 -5
index 30a9dca8f453..6264778ed9c3 100644
@@ -75,8 +75,12 @@ rtl8188e_PHY_QueryBBReg(
 	)
 {
 	u32 ReturnValue = 0, OriginalValue, BitShift;
+	int error;
+
+	OriginalValue = rtw_read32(Adapter, RegAddr, &error);
+	if (error)
+		return ReturnValue;
 
-	OriginalValue = rtw_read32(Adapter, RegAddr);
 	BitShift = phy_CalculateBitShift(BitMask);
 	ReturnValue = (OriginalValue & BitMask) >> BitShift;
 	return ReturnValue;
@@ -103,9 +107,12 @@ rtl8188e_PHY_QueryBBReg(
 void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
 {
 	u32 OriginalValue, BitShift;
+	int error;
 
 	if (BitMask != bMaskDWord) { /* if not "double word" write */
-		OriginalValue = rtw_read32(Adapter, RegAddr);
+		OriginalValue = rtw_read32(Adapter, RegAddr, &error);
+		if (error)
+			return;
 		BitShift = phy_CalculateBitShift(BitMask);
 		Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
 	}
@@ -577,11 +584,15 @@ PHY_BBConfig8188E(
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(Adapter);
 	u32 RegVal;
 	u8 CrystalCap;
+	int error;
 
 	phy_InitBBRFRegisterDefinition(Adapter);
 
 	/*  Enable BB and RF */
-	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN, &error);
+	if (error)
+		return -FAIL;
+
 	rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1)));
 
 	/*  20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
@@ -960,6 +971,7 @@ _PHY_SetBWMode92C(
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
 	u8 regBwOpMode;
 	u8 regRRSR_RSC;
+	int error;
 
 	if (pHalData->rf_chip == RF_PSEUDO_11N)
 		return;
@@ -975,8 +987,12 @@ _PHY_SetBWMode92C(
 	/* 3<1>Set MAC register */
 	/* 3 */
 
-	regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
-	regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2);
+	regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE, &error);
+	if (error)
+		return;
+	regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2, &error);
+	if (error)
+		return;
 
 	switch (pHalData->CurrentChannelBW) {
 	case HT_CHANNEL_WIDTH_20:
drivers/staging/r8188eu/hal/rtl8188e_sreset.c +16 -4
index 16fa249e35d3..1bb86629574d 100644
@@ -14,13 +14,16 @@ void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	unsigned long current_time;
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	unsigned int diff_time;
 	u32 txdma_status;
 
-	txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
+	txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS, &error);
+	if (error)
+		return;
+
 	if (txdma_status != 0x00) {
 		DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
 		rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
@@ -49,12 +52,21 @@ void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
 {
 	u32 rx_dma_status = 0;
 	u8 fw_status = 0;
-	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
+	int error;
+
+	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS, &error);
+	if (error)
+		return;
+
 	if (rx_dma_status != 0x00) {
 		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
 	}
-	fw_status = rtw_read8(padapter, REG_FMETHR);
+
+	fw_status = rtw_read8(padapter, REG_FMETHR, &error);
+	if (error)
+		return;
+
 	if (fw_status != 0x00) {
 		if (fw_status == 1)
 			DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
drivers/staging/r8188eu/hal/rtl8188eu_led.c +14 -3
index 452d4bb87aba..2467adb51f7d 100644
@@ -14,10 +14,15 @@
 void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return;
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);
+
+	LedCfg = rtw_read8(padapter, REG_LEDCFG2, &error);
+	if (error)
+		return;
+
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
 		rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /*  SW control led0 on. */
@@ -37,11 +42,14 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		goto exit;
 
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
+	LedCfg = rtw_read8(padapter, REG_LEDCFG2, &error);/* 0x4E */
+	if (error)
+		return;
 
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
@@ -49,7 +57,10 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 			/*  Open-drain arrangement for controlling the LED) */
 			LedCfg &= 0x90; /*  Set to software control. */
 			rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
-			LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
+			LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG, &error);
+			if (error)
+				return;
+
 			LedCfg &= 0xFE;
 			rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
 		} else {
drivers/staging/r8188eu/hal/usb_halinit.c +323 -71

790 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_ops_linux.c +9 -7
index 953fa05dc30c..980af6c02be5 100644
@@ -101,29 +101,31 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata,
 	return status;
 }
 
-static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
+static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr, int *error)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
 	u8 data = 0;
+	int res;
 
-
+	if (unlikely(!error))
+		WARN_ON_ONCE("r8188eu: Reading w/o error checking is bad idea\n");
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 1;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
-
-
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	if (likely(error))
+		*error = res < 0? res: 0;
 
 	return data;
 
 }
 
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr, int *error)
 {
 	u8 requesttype;
 	u16 wvalue;
@@ -138,7 +140,7 @@ static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
 	return (u16)(le32_to_cpu(data) & 0xffff);
 }
 
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr, int *error)
 {
 	u8 requesttype;
 	u16 wvalue;
drivers/staging/r8188eu/include/rtw_io.h +9 -9
index f1b3074fa075..7933c267b130 100644
@@ -85,9 +85,9 @@ struct intf_hdl;
 struct io_queue;
 
 struct _io_ops {
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
-	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr, int *error);
+	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr, int *error);
+	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
 	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
@@ -248,9 +248,9 @@ void unregister_intf_hdl(struct intf_hdl *pintfhdl);
 void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr);
-u16 _rtw_read16(struct adapter *adapter, u32 addr);
-u32 _rtw_read32(struct adapter *adapter, u32 addr);
+u8 _rtw_read8(struct adapter *adapter, u32 addr, int *error);
+u16 _rtw_read16(struct adapter *adapter, u32 addr, int *error);
+u32 _rtw_read32(struct adapter *adapter, u32 addr, int *error);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port_cancel(struct adapter *adapter);
@@ -270,9 +270,9 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
 			     u8 *pmem, int timeout_ms);
 void _rtw_write_port_cancel(struct adapter *adapter);
 
-#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr))
-#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
-#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
+#define rtw_read8(adapter, addr, err) _rtw_read8((adapter), (addr), (err))
+#define rtw_read16(adapter, addr, err) _rtw_read16((adapter), (addr), (err))
+#define rtw_read32(adapter, addr, err) _rtw_read32((adapter), (addr), (err))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
 	_rtw_read_mem((adapter), (addr), (cnt), (mem))
 #define rtw_read_port(adapter, addr, cnt, mem)				\
drivers/staging/r8188eu/os_dep/ioctl_linux.c +121 -47

364 lines not on this page · raw message

Signature · 1 line
2.32.0
#8 lore raw

RFC PATCH 2/3 staging: r8188eu: add error handling to ReadFuse

In reply to Pavel Skripkin

ReadEFuseByte() internally calls rtw_read8() which can fail. To avoid uninit value bugs we should properly handle error sutiation and deliver the error to caller.

To achieve it, some functions now return an int, and the error which could occur in ReadEFuseByte() is handled on the top level.

---
 drivers/staging/r8188eu/core/rtw_efuse.c      | 46 +++++++++-----
 drivers/staging/r8188eu/hal/hal_intf.c        |  6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 62 +++++++++++++------
 drivers/staging/r8188eu/hal/usb_halinit.c     | 20 ++++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 43 +++++++++++--
 drivers/staging/r8188eu/include/hal_intf.h    |  6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |  2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |  4 +-
 drivers/staging/r8188eu/os_dep/usb_intf.c     |  4 +-
 9 files changed, 138 insertions(+), 55 deletions(-)
drivers/staging/r8188eu/core/rtw_efuse.c +31 -15
index 47ff73b28380..5fcff0d6eb26 100644
@@ -149,7 +149,7 @@ Efuse_CalculateWordCnts(u8 word_en)
 /*  */
 /* 	Created by Roger, 2008.10.21. */
 /*  */
-void
+int
 ReadEFuseByte(
 		struct adapter *Adapter,
 		u16 _offset,
@@ -163,32 +163,32 @@ ReadEFuseByte(
 
 	if (pseudo) {
 		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
-		return;
+		return 0;
 	}
 
 	/* Write Address */
 	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2, &error);
 	if (error)
-		return;
+		return error;
 	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 
 	/* Write bit 32 0 */
 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3, &error);
 	if (error)
-		return;
+		return error;
 	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
 
 	/* Check bit 32 read-ready */
 	retry = 0;
 	value32 = rtw_read32(Adapter, EFUSE_CTRL, &error);
 	if (error)
-		return;
+		return error;
 
 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
 		value32 = rtw_read32(Adapter, EFUSE_CTRL, &error);
 		if (error)
-			return;
+			return error;
 		retry++;
 	}
 
@@ -199,9 +199,11 @@ ReadEFuseByte(
 	udelay(50);
 	value32 = rtw_read32(Adapter, EFUSE_CTRL, &error);
 	if (error)
-		return;
+		return error;
 
 	*pbuf = (u8)(value32 & 0xff);
+
+	return 0;
 }
 
 /*  */
@@ -222,9 +224,9 @@ ReadEFuseByte(
 /* 					write addr must be after sec5. */
 /*  */
 
-static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
+static int efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
 {
-	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
+	return Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
 }
 
 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
@@ -539,6 +541,7 @@ u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int res;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -547,7 +550,9 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	res = efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	if (res)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -557,6 +562,7 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int res;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -565,7 +571,9 @@ u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	res = efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	if (res)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -836,17 +844,22 @@ efuse_ShadowRead4Byte(
  * 11/11/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+static int Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
 {
 	u16 mapLen = 0;
+	int res;
 
 	Efuse_PowerSwitch(pAdapter, false, true);
 
 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 
-	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	res = efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	if (res)
+		return res;
 
 	Efuse_PowerSwitch(pAdapter, false, false);
+
+	return res;
 }
 
 /*-----------------------------------------------------------------------------
@@ -865,20 +878,23 @@ static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse,
  * 11/13/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-void EFUSE_ShadowMapUpdate(
+int EFUSE_ShadowMapUpdate(
 	struct adapter *pAdapter,
 	u8 efuseType,
 	bool pseudo)
 {
 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 	u16 mapLen = 0;
+	int res = 0;
 
 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 
 	if (pEEPROM->bautoload_fail_flag)
 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 	else
-		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+		res = Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+
+	return res;
 } /*  EFUSE_ShadowMapUpdate */
 
 /*-----------------------------------------------------------------------------
drivers/staging/r8188eu/hal/hal_intf.c +4 -2
index a6d589e89aeb..94536659cd7c 100644
@@ -12,10 +12,12 @@ void rtw_hal_chip_configure(struct adapter *adapt)
 		adapt->HalFunc.intf_chip_configure(adapt);
 }
 
-void rtw_hal_read_chip_info(struct adapter *adapt)
+int rtw_hal_read_chip_info(struct adapter *adapt)
 {
 	if (adapt->HalFunc.read_adapter_info)
-		adapt->HalFunc.read_adapter_info(adapt);
+		return adapt->HalFunc.read_adapter_info(adapt);
+
+	return 0;
 }
 
 void rtw_hal_read_chip_version(struct adapter *adapt)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +43 -19

155 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_halinit.c +14 -6
index 73ef2e0ead19..8df8a8b7c738 100644
@@ -1275,7 +1275,7 @@ readAdapterInfo_8188EU(
 	_ReadLEDSetting(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
 }
 
-static void _ReadPROMContent(
+static int _ReadPROMContent(
 	struct adapter *Adapter
 	)
 {
@@ -1286,7 +1286,7 @@ static void _ReadPROMContent(
 	/* check system boot selection */
 	eeValue = rtw_read8(Adapter, REG_9346CR, &error);
 	if (error)
-		return;
+		return error;
 
 	eeprom->EepromOrEfuse		= (eeValue & BOOT_FROM_EEPROM) ? true : false;
 	eeprom->bautoload_fail_flag	= (eeValue & EEPROM_EN) ? false : true;
@@ -1294,8 +1294,13 @@ static void _ReadPROMContent(
 	DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"),
 		(eeprom->bautoload_fail_flag ? "Fail" : "OK"));
 
-	Hal_InitPGData88E(Adapter);
+	error = Hal_InitPGData88E(Adapter);
+	if (error)
+		return error;
+
 	readAdapterInfo_8188EU(Adapter);
+
+	return 0;
 }
 
 static void _ReadRFType(struct adapter *Adapter)
@@ -1308,23 +1313,26 @@ static void _ReadRFType(struct adapter *Adapter)
 static int _ReadAdapterInfo8188EU(struct adapter *Adapter)
 {
 	u32 start = jiffies;
+	int res;
 
 	MSG_88E("====> %s\n", __func__);
 
 	_ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
-	_ReadPROMContent(Adapter);
+	res = _ReadPROMContent(Adapter);
+	if (res)
+		return _FAIL;
 
 	MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
 
 	return _SUCCESS;
 }
 
-static void ReadAdapterInfo8188EU(struct adapter *Adapter)
+static int ReadAdapterInfo8188EU(struct adapter *Adapter)
 {
 	/*  Read EEPROM size before call any EEPROM function */
 	Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter);
 
-	_ReadAdapterInfo8188EU(Adapter);
+	return _ReadAdapterInfo8188EU(Adapter);
 }
 
 #define GPIO_DEBUG_PORT_NUM 0
drivers/staging/r8188eu/hal/usb_ops_linux.c +37 -6

71 lines not on this page · raw message

drivers/staging/r8188eu/include/hal_intf.h +3 -3
index fa252540e596..9241af39e3a3 100644
@@ -154,7 +154,7 @@ struct hal_ops {
 
 	void	(*intf_chip_configure)(struct adapter *padapter);
 
-	void	(*read_adapter_info)(struct adapter *padapter);
+	int	(*read_adapter_info)(struct adapter *padapter);
 
 	void	(*enable_interrupt)(struct adapter *padapter);
 	void	(*disable_interrupt)(struct adapter *padapter);
@@ -222,7 +222,7 @@ struct hal_ops {
 
 	void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite,
 				 u8 PwrState);
-	void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
+	int (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
 			  u16 _size_byte, u8 *pbuf, bool bPseudoTest);
 	void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType,
 					u8 type, void *pOut, bool bPseudoTest);
@@ -324,7 +324,7 @@ void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 
 void rtw_hal_chip_configure(struct adapter *padapter);
-void rtw_hal_read_chip_info(struct adapter *padapter);
+int rtw_hal_read_chip_info(struct adapter *padapter);
 void rtw_hal_read_chip_version(struct adapter *padapter);
 
 u8 rtw_hal_set_def_var(struct adapter *padapter,
drivers/staging/r8188eu/include/rtl8188e_hal.h +1 -1
index 3939bf053de1..db9adbd0b024 100644
@@ -410,7 +410,7 @@ s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy);
 
 /*  EFuse */
 u8 GetEEPROMSize8188E(struct adapter *padapter);
-void Hal_InitPGData88E(struct adapter *padapter);
+int Hal_InitPGData88E(struct adapter *padapter);
 void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo);
 void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo,
 			    bool AutoLoadFail);
drivers/staging/r8188eu/include/rtw_efuse.h +2 -2
index b3ff46db2091..9657b66679e3 100644
@@ -113,7 +113,7 @@ u8 rtw_BT_efuse_map_write(struct adapter *adapter, u16 addr,
 			  u16 cnts, u8 *data);
 u16 Efuse_GetCurrentSize(struct adapter *adapter, u8 efusetype, bool test);
 u8 Efuse_CalculateWordCnts(u8 word_en);
-void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
+int ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
 void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1,
 			      void *out, bool bPseudoTest);
 u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data, bool test);
@@ -128,7 +128,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
 			     u8 word_en, u8 *data, bool test);
 
 u8 EFUSE_Read1Byte(struct adapter *adapter, u16 address);
-void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
+int EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
 void EFUSE_ShadowRead(struct adapter *adapt, u8 type, u16 offset, u32 *val);
 
 #endif
drivers/staging/r8188eu/os_dep/usb_intf.c +3 -1
index e002070f7fba..f950a31d061e 100644
@@ -608,7 +608,9 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
 	rtw_hal_chip_configure(padapter);
 
 	/* step read efuse/eeprom data and get mac_addr */
-	rtw_hal_read_chip_info(padapter);
+	status = rtw_hal_read_chip_info(padapter);
+	if (status)
+		goto free_hal_data;
 
 	/* step 5. */
 	if (rtw_init_drv_sw(padapter) == _FAIL)
Signature · 1 line
2.32.0
#11 lore raw

RFC PATCH 3/3 staging: r8188eu: add error argument to read_macreg

In reply to Pavel Skripkin

Since read_macreg() calls rtw_read*() internally we should tell callers about an error on the read side.

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 9 ++++-----
 drivers/staging/r8188eu/include/rtw_mp.h | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)
drivers/staging/r8188eu/core/rtw_mp.c +4 -5
index 601a1fd5d4e7..6bbea1cc364a 100644
@@ -7,20 +7,19 @@
 #include "../include/odm_precomp.h"
 #include "../include/rtl8188e_hal.h"
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
+u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz, int *error)
 {
 	u32 val = 0;
-	int error;
 
 	switch (sz) {
 	case 1:
-		val = rtw_read8(padapter, addr, &error);
+		val = rtw_read8(padapter, addr, error);
 		break;
 	case 2:
-		val = rtw_read16(padapter, addr, &error);
+		val = rtw_read16(padapter, addr, error);
 		break;
 	case 4:
-		val = rtw_read32(padapter, addr, &error);
+		val = rtw_read32(padapter, addr, error);
 		break;
 	default:
 		val = 0xffffffff;
drivers/staging/r8188eu/include/rtw_mp.h +1 -1
index b64b16554343..c063e6216249 100644
@@ -410,7 +410,7 @@ void mp_stop_test(struct adapter *padapter);
 u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask);
 void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val);
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
+u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz, int *error);
 void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
 u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
 void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
Signature · 1 line
2.32.0
#2 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

In reply to Pavel Skripkin
reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross #…

Hi Pavel,

[FYI, it's a private test report for your RFC patch.] [auto build test WARNING on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-avoid-uninit-value-bugs/20210821-010950
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: nds32-allyesconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 11.2.0

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/8d87387f4b20dda71cac89849786695d608f9e84
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-avoid-uninit-value-bugs/20210821-010950 git checkout 8d87387f4b20dda71cac89849786695d608f9e84
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=nds32

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

drivers/staging/r8188eu/hal/hal_com.c: In function 'c2h_evt_read':

>> drivers/staging/r8188eu/hal/hal_com.c:347:17: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
     347 |                 ;
         |                 ^

vim +/if +347 drivers/staging/r8188eu/hal/hal_com.c

317
318 s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
319 {
320 s32 ret = _FAIL;
321 struct c2h_evt_hdr *c2h_evt;
322 int i, error;
323 u8 trigger;
324
325 if (!buf)
326 goto exit;
327
328 trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR, &error);
329 if (error)
330 goto exit;
331
332 if (trigger == C2H_EVT_HOST_CLOSE)
333 goto exit; /* Not ready */
334 else if (trigger != C2H_EVT_FW_CLOSE)
335 goto clear_evt; /* Not a valid value */
336
337 c2h_evt = (struct c2h_evt_hdr *)buf;
338
339 memset(c2h_evt, 0, 16);
340
341 *buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, &error);
342 if (error)
343 goto clear_evt;
344
345 *(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, &error);
346 if (error)

 > 347			;

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#3 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

In reply to Pavel Skripkin

On 8/20/21 8:07 PM, Pavel Skripkin wrote:
[snip]

drivers/staging/r8188eu/hal/hal_com.c s32 c2h_evt_read(struct adapter *adapter, u8 *buf) · line 347

Quoted 13 lines
drivers/staging/r8188eu/hal/hal_com.c +7 -2
@@ -336,13 +338,21 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 
  	memset(c2h_evt, 0, 16);
 
-	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
-	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
+	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, &error);
+	if (error)
+		goto clear_evt;
+
+	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, &error);
+	if (error)
+		;
	 ^^^^^^^

Should be goto clear_evt;. Will fix in v2, I want to receive some feedback first :)

With regards,
Pavel Skripkin

#14 lore raw
In reply to Pavel Skripkin
Quoted 70 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided
to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but
it can fail and driver may start writing random stack values into registers. It
can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've expanded read() API with error parametr,
which will be initialized to error if read fails. It helps callers to break/return earlier and don't write random values to registers or to rely
on random values.

Why is this pacth series RFC?
  1. I don't have this device and I cannot test these changes.
  2. I don't know how to handle errors in each particular case. For now, function
     just returns or returns an error. That's all. I hope, driver maintainers will
     help with these bits.
  3. I guess, I handled not all uninit value bugs here. I hope, I fixed
     at least half of them

This series was build-tested and made on top of staging-testing branch

With regards,
Pavel Skripkin

Pavel Skripkin (3):
  staging: r8188eu: add proper rtw_read* error handling
  staging: r8188eu: add error handling to ReadFuse
  staging: r8188eu: add error argument to read_macreg

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++- drivers/staging/r8188eu/core/rtw_efuse.c      | 119 +++-- drivers/staging/r8188eu/core/rtw_io.c         |  18 +- drivers/staging/r8188eu/core/rtw_mp.c         |  38 +- drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +- drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +- drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +- drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +- drivers/staging/r8188eu/hal/hal_com.c         |  22 +- drivers/staging/r8188eu/hal/hal_intf.c        |   6 +- drivers/staging/r8188eu/hal/odm_interface.c   |  12 +- drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +- drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +- .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 260 ++++++++--- drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +- drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +- drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +- drivers/staging/r8188eu/hal/usb_halinit.c     | 412 ++++++++++++++-- --
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  55 ++- drivers/staging/r8188eu/include/hal_intf.h    |   6 +- .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +- drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +- drivers/staging/r8188eu/include/rtw_io.h      |  18 +- drivers/staging/r8188eu/include/rtw_mp.h      |   2 +- drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++-- drivers/staging/r8188eu/os_dep/usb_intf.c     |   4 +-

Quoted 2 lines
 26 files changed, 1072 insertions(+), 301 deletions(-)

Dear Pavel,

Firstly, thank you for this contribution, it is much appreciated. Whilst I'm still learning myself when it comes to this driver and to kernel code in general, I can certainly say the code looks pretty good in general so far. I will try and offer individual comments on each patch.

Regards,
Phil

#12 lore raw

Re: [PATCH RFC 3/3] staging: r8188eu: add error argument to read_macreg

In reply to Pavel Skripkin
Quoted 20 lines · Pavel Skripkin

Since read_macreg() calls rtw_read*() internally we should tell callers about an error on the read side.

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 9 ++++----- drivers/staging/r8188eu/include/rtw_mp.h | 2 +-

 2 files changed, 5 insertions(+), 6 deletions(-)
drivers/staging/r8188eu/core/rtw_mp.c +0 -0
index 601a1fd5d4e7..6bbea1cc364a 100644
@@ -7,20 +7,19 @@
  #include "../include/odm_precomp.h"
  #include "../include/rtl8188e_hal.h"

drivers/staging/r8188eu/core/rtw_mp.c +1 -1
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
+u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz, int
Quoted 1 line

*error)

Dear Pavel,

Correct me if I'm wrong, but this read_macreg function seems to be completely unused by the rest of the driver. Rather than changing the signature to do error handling, maybe it would be better to just remove it?

That is just my view though, would be interested to see what others think - perhaps it could come in handy at some point.

Regards,
Phil

#4 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

In reply to Pavel Skripkin
Quoted 42 lines · Pavel Skripkin

rtw_read*() functions call usb_read* inside. These functions could fail
in some cases; for example: failed to receive control message. These cases should be handled to prevent uninit value bugs, since usb_read* functions blindly return stack variable without checking if this value
_actualy_ initialized.

To achive it, all usb_read* and rtw_read*() argument list is expanded with pointer to error and added error usbctrl_vendorreq() error checking.
If transfer is successful error will be initialized to 0 otherwise to error returned from usb_control_msg().

To not break the build, added error checking for rtw_read*() call all across the driver.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++- drivers/staging/r8188eu/core/rtw_efuse.c      |  83 +++- drivers/staging/r8188eu/core/rtw_io.c         |  18 +- drivers/staging/r8188eu/core/rtw_mp.c         |  37 +- drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +- drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +- drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +- drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +- drivers/staging/r8188eu/hal/hal_com.c         |  22 +- drivers/staging/r8188eu/hal/odm_interface.c   |  12 +- drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +- drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +- .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 198 +++++++-- drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +- drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +- drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +- drivers/staging/r8188eu/hal/usb_halinit.c     | 394 ++++++++++++++-- --
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  16 +- drivers/staging/r8188eu/include/rtw_io.h      |  18 +- drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++---

 20 files changed, 941 insertions(+), 252 deletions(-)

...

Quoted 54 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +0 -0
index 953fa05dc30c..980af6c02be5 100644
@@ -101,29 +101,31 @@ static int usbctrl_vendorreq(struct intf_hdl
 *pintfhdl, u16 value, void *pdata,
         return status;
  }

drivers/staging/r8188eu/hal/usb_ops_linux.c +1 -1
-static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
+static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr, int *error)

 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
        u8 data = 0;
+       int res;

-
+       if (unlikely(!error))
+               WARN_ON_ONCE("r8188eu: Reading w/o error checking is bad idea\n");

        requesttype = 0x01;/* read_in */

        wvalue = (u16)(addr & 0x0000ffff);
        len = 1;

-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

drivers/staging/r8188eu/hal/usb_ops_linux.c +1 -2
-
-
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len,

requesttype);
+       if (likely(error))
+               *error = res < 0? res: 0;

        return data;

 }

drivers/staging/r8188eu/hal/usb_ops_linux.c +1 -1
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr, int

*error)
 {
        u8 requesttype;
        u16 wvalue;

drivers/staging/r8188eu/hal/usb_ops_linux.c +0 -0
@@ -138,7 +140,7 @@ static u16 usb_read16(struct intf_hdl *pintfhdl,
 u32 addr)
         return (u16)(le32_to_cpu(data) & 0xffff);
  }

drivers/staging/r8188eu/hal/usb_ops_linux.c +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr, int
Quoted 4 lines

*error)
 {
        u8 requesttype;
        u16 wvalue;

Dear Pavel,

For this patch, you modify the signature of the usb_read*() functions, but only introduce the usbctrl_vendorreq checks for usb_read8.

I can see from the following patch that you have done the others too later on, but really I would say for changes like this, they should be grouped in the same patch. Also, just me nitpicking probably, but the patch is rather large - sometimes unavoidable I know, but perhaps better to group logically into areas (files or types of change) in order to get the patches smaller and thus more easily reviewable. Many thanks.

In terms of what we do with the errors, I would invite comments from others on this too due to my inexperience, but I like your thinking.

Regards,
Phil

#9 lore raw

Re: [PATCH RFC 2/3] staging: r8188eu: add error handling to ReadFuse

In reply to Pavel Skripkin
Quoted 9 lines · Pavel Skripkin

ReadEFuseByte() internally calls rtw_read8() which can fail. To avoid uninit value bugs we should properly handle error sutiation and deliver the error to caller.

To achieve it, some functions now return an int, and the error which could occur in ReadEFuseByte() is handled on the top level.

Quoted 12 lines
---
 drivers/staging/r8188eu/core/rtw_efuse.c      | 46 +++++++++-----
 drivers/staging/r8188eu/hal/hal_intf.c        |  6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 62 +++++++++++++------
 drivers/staging/r8188eu/hal/usb_halinit.c     | 20 ++++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 43 +++++++++++--
 drivers/staging/r8188eu/include/hal_intf.h    |  6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |  2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |  4 +-
 drivers/staging/r8188eu/os_dep/usb_intf.c     |  4 +-
 9 files changed, 138 insertions(+), 55 deletions(-)

Dear Pavel,

I like the code, just a few things though:
(1) the comments I made in the previous e-mail r.e. what we actually do with the errors, and grouping logically related changes (the rest of the usb_read*() changes being in this patch for example).
(2) I got trailing whitespace errors from this patch and the last one. For a v2 I would say stripping the whitespace is a good idea too - I have submitted many patches myself to this driver that had whitespace in - indeed, the original version of my patch series to import the driver still had a load as well :-)

Regards,
Phil

#10 lore raw

Re: [PATCH RFC 2/3] staging: r8188eu: add error handling to ReadFuse

Dear Pavel

Quoted 4 lines · CEST Phillip Potter
Quoted 3 lines · Pavel Skripkin

ReadEFuseByte() internally calls rtw_read8() which can fail. To avoid uninit value bugs we should properly handle error sutiation and deliver

sutiation --> situation.

Quoted 5 lines
Quoted 5 lines

the error to caller.

To achieve it, some functions now return an int, and the error which could occur in ReadEFuseByte() is handled on the top level.

Quoted 13 lines
Quoted 13 lines
---
 drivers/staging/r8188eu/core/rtw_efuse.c      | 46 +++++++++-----
 drivers/staging/r8188eu/hal/hal_intf.c        |  6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 62 +++++++++++++------
 drivers/staging/r8188eu/hal/usb_halinit.c     | 20 ++++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 43 +++++++++++--
 drivers/staging/r8188eu/include/hal_intf.h    |  6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |  2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |  4 +-
 drivers/staging/r8188eu/os_dep/usb_intf.c     |  4 +-
 9 files changed, 138 insertions(+), 55 deletions(-)

Please change the Subject: ReadFuse --> ReadEFuse() or ReadFuse --> ReadEFuseByte().

Quoted 7 lines

Dear Pavel,

I like the code, just a few things though:
(1) the comments I made in the previous e-mail r.e. what we actually do with the errors, and grouping logically related changes (the rest of the usb_read*() changes being in this patch for example).

I agree with Philip on splitting 1/3 into more patches, perhaps one for each of the three rtw_read*(), but I disagree on merging the usb_read*() changes into this. They should go to another patch because they are not strictly related to "add[ing] error handling to ReadFuse".

Regards,

Fabio

Quoted 9 lines

(2) I got trailing whitespace errors from this patch and the last one. For a v2 I would say stripping the whitespace is a good idea too - I have submitted many patches myself to this driver that had whitespace in - indeed, the original version of my patch series to import the driver still had a load as well :-)

Regards,
Phil

#5 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

In reply to Pavel Skripkin
Quoted 7 lines · CEST Pavel Skripkin

rtw_read*() functions call usb_read* inside. These functions could fail in some cases; for example: failed to receive control message. These cases should be handled to prevent uninit value bugs, since usb_read* functions blindly return stack variable without checking if this value _actualy_ initialized.

To achive it, all usb_read* and rtw_read*() argument list is expanded

Dear Pavel,

Please, achive --> achieve.

Quoted 22 lines

with pointer to error and added error usbctrl_vendorreq() error checking. If transfer is successful error will be initialized to 0 otherwise to error returned from usb_control_msg().

To not break the build, added error checking for rtw_read*() call all across the driver.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      |  83 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  18 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  37 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  22 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 198 +++++++--
Quoted 8 lines
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 394 ++++++++++++++----
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  16 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++---
 20 files changed, 941 insertions(+), 252 deletions(-)

I agree with Philip: please, split this long patch. If I were you, I'd make one patch for each of the three rtw_read*() and a fourth patch for usb_read*().

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 35

Quoted 5 lines
drivers/staging/r8188eu/core/rtw_io.c +0 -0
@@ -34,44 +34,44 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)

Not related to your patch, these macros are useless and misleading.

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_io.c +1 -1
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
+u8 _rtw_read8(struct adapter *adapter, u32 addr, int *error)
 {
 	u8 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl *pintfhdl = &pio_priv->intf;

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 49

Quoted 10 lines
drivers/staging/r8188eu/core/rtw_io.c +2 -2
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 
 	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
+	r_val = _read8(pintfhdl, addr, error);
 
 	return r_val;
 }

I really don't like passing errors through arguments. Why don't you pass a storage location where the function save the byte read and instead use the return for errors? I think that this would result in a cleaner design. Furthermore, it is used everywhere in the kernel.

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_io.c +1 -1
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+u16 _rtw_read16(struct adapter *adapter, u32 addr, int *error)
 {
 	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 63

Quoted 10 lines
drivers/staging/r8188eu/core/rtw_io.c +2 -2
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read16 = pintfhdl->io_ops._read16;
 
-	r_val = _read16(pintfhdl, addr);
+	r_val = _read16(pintfhdl, addr, error);
 
 	return r_val;
 }

Same.

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_io.c +1 -1
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
+u32 _rtw_read32(struct adapter *adapter, u32 addr, int *error)
 {
 	u32 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 77

Quoted 10 lines
drivers/staging/r8188eu/core/rtw_io.c +2 -2
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read32 = pintfhdl->io_ops._read32;
 
-	r_val = _read32(pintfhdl, addr);
+	r_val = _read32(pintfhdl, addr, error);
 
 	return r_val;
 }

Same.

I'm done for now: too many lines to read all at once :)

Regards,

Fabio

#6 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

Quoted 7 lines · Fabio M. De Francesco
Quoted 6 lines · CEST Pavel Skripkin

rtw_read*() functions call usb_read* inside. These functions could fail in some cases; for example: failed to receive control message. These cases should be handled to prevent uninit value bugs, since usb_read* functions blindly return stack variable without checking if this value _actualy_ initialized.

Quoted 37 lines
Quoted 1 line

To achive it, all usb_read* and rtw_read*() argument list is expanded

Dear Pavel,

Please, achive --> achieve.

Quoted 30 lines

with pointer to error and added error usbctrl_vendorreq() error checking. If transfer is successful error will be initialized to 0 otherwise to error returned from usb_control_msg().

To not break the build, added error checking for rtw_read*() call all across the driver.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      |  83 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  18 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  37 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  22 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 198 +++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 394 ++++++++++++++----
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  16 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++---
 20 files changed, 941 insertions(+), 252 deletions(-)

Hi, Fabio!

Thank you for feedback

Quoted 3 lines

I agree with Philip: please, split this long patch. If I were you, I'd make one patch for each of the three rtw_read*() and a fourth patch for usb_read*().

Make sense. Will fix in v2.

Quoted 8 lines

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 35

Quoted 5 lines
drivers/staging/r8188eu/core/rtw_io.c +0 -0
@@ -34,44 +34,44 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)

Not related to your patch, these macros are useless and misleading.

Sorry, I don't get it. I didn't touch these macros, it's part of diffstat.

Quoted 14 lines
Quoted 14 lines
drivers/staging/r8188eu/core/rtw_io.c +3 -3
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
+u8 _rtw_read8(struct adapter *adapter, u32 addr, int *error)
 {
 	u8 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl *pintfhdl = &pio_priv->intf;
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 
 	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
+	r_val = _read8(pintfhdl, addr, error);
 
Quoted 8 lines

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 48

Quoted 2 lines
drivers/staging/r8188eu/core/rtw_io.c +0 -0
 	return r_val;
 }

I really don't like passing errors through arguments. Why don't you pass a storage location where the function save the byte read and instead use the return for errors? I think that this would result in a cleaner design. Furthermore, it is used everywhere in the kernel.

Yep, this will be more cleaner, but I decided to receive some feedback first about the idea. If this error handling is really necessary, I will rework this approach :)

Quoted 33 lines
Quoted 6 lines
drivers/staging/r8188eu/core/rtw_io.c +1 -1
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+u16 _rtw_read16(struct adapter *adapter, u32 addr, int *error)
 {
 	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 63

Quoted 10 lines
drivers/staging/r8188eu/core/rtw_io.c +2 -2
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read16 = pintfhdl->io_ops._read16;
 
-	r_val = _read16(pintfhdl, addr);
+	r_val = _read16(pintfhdl, addr, error);
 
 	return r_val;
 }

Same.

Quoted 14 lines
drivers/staging/r8188eu/core/rtw_io.c +3 -3
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
+u32 _rtw_read32(struct adapter *adapter, u32 addr, int *error)
 {
 	u32 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr, int *error);
 
 	_read32 = pintfhdl->io_ops._read32;
 
-	r_val = _read32(pintfhdl, addr);
+	r_val = _read32(pintfhdl, addr, error);
 
Quoted 7 lines

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 74

Quoted 2 lines
drivers/staging/r8188eu/core/rtw_io.c +0 -0
 	return r_val;
 }

Same.

I'm done for now: too many lines to read all at once :)

With regards,
Pavel Skripkin

#13 lore raw

Re: [PATCH RFC 3/3] staging: r8188eu: add error argument to read_macreg

In reply to Phillip Potter
Quoted 25 lines · Phillip Potter
Quoted 15 lines · Pavel Skripkin

Since read_macreg() calls rtw_read*() internally we should tell callers about an error on the read side.

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 9 ++++----- drivers/staging/r8188eu/include/rtw_mp.h | 2 +-

 2 files changed, 5 insertions(+), 6 deletions(-)
drivers/staging/r8188eu/core/rtw_mp.c +0 -0
index 601a1fd5d4e7..6bbea1cc364a 100644

drivers/staging/r8188eu/core/rtw_mp.c line 11

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_mp.c +1 -1
@@ -7,20 +7,19 @@
  #include "../include/odm_precomp.h"
  #include "../include/rtl8188e_hal.h"
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
+u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz, int
 *error)

Dear Pavel,

Quoted 8 lines

Correct me if I'm wrong, but this read_macreg function seems to be completely unused by the rest of the driver. Rather than changing the signature to do error handling, maybe it would be better to just remove it?

That is just my view though, would be interested to see what others think - perhaps it could come in handy at some point.

yes, this function is unused for now, but I am aware about plans for this function :) If no one has plans for it, it can be removed.

With regards,
Pavel Skripkin

#15 lore raw
In reply to Phillip Potter
Quoted 74 lines · Phillip Potter
Quoted 70 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided
to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but
it can fail and driver may start writing random stack values into registers. It
can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've expanded read() API with error parametr,
which will be initialized to error if read fails. It helps callers to break/return earlier and don't write random values to registers or to rely
on random values.

Why is this pacth series RFC?
  1. I don't have this device and I cannot test these changes.
  2. I don't know how to handle errors in each particular case. For now, function
     just returns or returns an error. That's all. I hope, driver maintainers will
     help with these bits.
  3. I guess, I handled not all uninit value bugs here. I hope, I fixed
     at least half of them

This series was build-tested and made on top of staging-testing branch

With regards,
Pavel Skripkin

Pavel Skripkin (3):
  staging: r8188eu: add proper rtw_read* error handling
  staging: r8188eu: add error handling to ReadFuse
  staging: r8188eu: add error argument to read_macreg

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++- drivers/staging/r8188eu/core/rtw_efuse.c      | 119 +++-- drivers/staging/r8188eu/core/rtw_io.c         |  18 +- drivers/staging/r8188eu/core/rtw_mp.c         |  38 +- drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  20 +- drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   6 +- drivers/staging/r8188eu/core/rtw_sreset.c     |   7 +- drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +- drivers/staging/r8188eu/hal/hal_com.c         |  22 +- drivers/staging/r8188eu/hal/hal_intf.c        |   6 +- drivers/staging/r8188eu/hal/odm_interface.c   |  12 +- drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  37 +- drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +- .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 260 ++++++++--- drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  26 +- drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  20 +- drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  17 +- drivers/staging/r8188eu/hal/usb_halinit.c     | 412 ++++++++++++++-- --
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  55 ++- drivers/staging/r8188eu/include/hal_intf.h    |   6 +- .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +- drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +- drivers/staging/r8188eu/include/rtw_io.h      |  18 +- drivers/staging/r8188eu/include/rtw_mp.h      |   2 +- drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 168 +++++-- drivers/staging/r8188eu/os_dep/usb_intf.c     |   4 +-

Quoted 2 lines
 26 files changed, 1072 insertions(+), 301 deletions(-)
Quoted 8 lines

Dear Pavel,

Firstly, thank you for this contribution, it is much appreciated. Whilst I'm still learning myself when it comes to this driver and to kernel code in general, I can certainly say the code looks pretty good in general so far. I will try and offer individual comments on each patch.

Thank you for your feedback. So, I will prepare a v2 version in few days and, I think, I will leave RFC prefix.

Also, I want to receive some feedback from Larry about error handling in each particular case, I guess, he can help us with it.

So, I will split each rtw_read* changes into separate patche and make them return an error instead of read value.

Again, big thanks to you and Fabio for feedback, I appreciate it :)

With regards,
Pavel Skripkin

#7 lore raw

Re: [PATCH RFC 1/3] staging: r8188eu: add proper rtw_read* error handling

In reply to Pavel Skripkin
Quoted 21 lines · CEST Pavel Skripkin
Quoted 11 lines · Fabio M. De Francesco
Quoted 7 lines · CEST Pavel Skripkin

rtw_read*() functions call usb_read* inside. These functions could fail in some cases; for example: failed to receive control message. These cases should be handled to prevent uninit value bugs, since usb_read* functions blindly return stack variable without checking if this value _actualy_ initialized.

To achive it, all usb_read* and rtw_read*() argument list is expanded

[]

Quoted 8 lines

drivers/staging/r8188eu/core/rtw_io.c [email protected] · line 35

Quoted 5 lines
drivers/staging/r8188eu/core/rtw_io.c +0 -0
@@ -34,44 +34,44 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)

Not related to your patch, these macros are useless and misleading.

Quoted 1 line

Sorry, I don't get it. I didn't touch these macros, it's part of diffstat.

Yes, correct; in fact I wrote: "not related to your patch".

I just saw those macros while reading your patch. The code is I just noticed that those macros are useless (in case someone wanted to
address that issue).

Obviously, if you find it interesting, you shouldn't do that in your series, because it is entirely unrelated to the purpose of your work.

I hope now I've made it clearer, sorry.

Regards,

Fabio

#16 lore raw
In reply to Pavel Skripkin
Quoted 6 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result,

but

Quoted 1 line

it can fail and driver may start writing random stack values into registers.

It

Quoted 1 line

can cause driver misbehavior or device misbehavior.

After the messages I wrote yesterday, I had some minutes to look deeper at the code that would be changed by these patches.

I think that it does not look like that the driver could return "random stack values into registers" and I think this entire series in unnecessary.

As far as I understand this driver (though I must admit that I really don't know how to write drivers, and I'm not interested in understanding - at the moment, at least), all the usb_read*() call usbctrl_vendorreq() and the latter *does* proper error checking before returning to the callers the read data.

Please, look at the code copied from usbctrl_vendorreq() and pasted here (some comments are mine):

/* start of code */
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
{

/* test if everything is OK for transfers and setup the necessary variables */ [...]

status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,
reqtype, value,
REALTEK_USB_VENQT_CMD_IDX,
pIo_buf, len,
RTW_USB_CONTROL_MSG_TIMEOUT);

                if (status == len) {   /*  Success this control transfer. */
                        rtw_reset_continual_urb_error(dvobjpriv);
                        if (requesttype == 0x01)
                                memcpy(pdata, pIo_buf,  len); /* pdata 
receives the read data */
	} else { /*  error cases */

[...]

}
/* end of code */

So, *I cannot ack this RFC*, unless maintainers say I'm missing something.

Larry, Philip, since you have much more knowledge than me about r8188eu (and, more in general, on device drivers) may you please say what you think about my arguments against this series?

Thanks,

Fabio

Quoted 8 lines

To avoid this type of bugs, i've expanded read() API with error parametr, which will be initialized to error if read fails. It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now,

function

Quoted 1 line

just returns or returns an error. That's all. I hope, driver

maintainers will

Quoted 9 lines

help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

This series was build-tested and made on top of staging-testing branch

With regards,
Pavel Skripkin

#17 lore raw
Quoted 49 lines · Fabio M. De Francesco
Quoted 6 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result,

but

Quoted 1 line

it can fail and driver may start writing random stack values into registers.

It

Quoted 1 line

can cause driver misbehavior or device misbehavior.

After the messages I wrote yesterday, I had some minutes to look deeper at the code that would be changed by these patches.

I think that it does not look like that the driver could return "random stack values into registers" and I think this entire series in unnecessary.

As far as I understand this driver (though I must admit that I really don't know how to write drivers, and I'm not interested in understanding - at the moment, at least), all the usb_read*() call usbctrl_vendorreq() and the latter *does* proper error checking before returning to the callers the read data.

Please, look at the code copied from usbctrl_vendorreq() and pasted here (some comments are mine):

/* start of code */
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
{

/* test if everything is OK for transfers and setup the necessary variables */ [...]

status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,
reqtype, value,
REALTEK_USB_VENQT_CMD_IDX,
pIo_buf, len,
RTW_USB_CONTROL_MSG_TIMEOUT);

                 if (status == len) {   /*  Success this control transfer. */
                         rtw_reset_continual_urb_error(dvobjpriv);
                         if (requesttype == 0x01)
                                 memcpy(pdata, pIo_buf,  len); /* pdata
receives the read data */
	} else { /*  error cases */

[...]

Quoted 9 lines

}
/* end of code */

So, *I cannot ack this RFC*, unless maintainers say I'm missing something.

Larry, Philip, since you have much more knowledge than me about r8188eu (and, more in general, on device drivers) may you please say what you think about my arguments against this series?

Hi, Fabio!

Thank you for looking into this, but I still can see the case when pdata won't be initialized:

pdata is initialized only in case of successful transfer, i.e len > 0. It means some data was received (maybe not full length, but anyway). In case of usb_control_msg() error (for example -ENOMEM) code only does this code block:

if (status < 0) {
	if (status == (-ESHUTDOWN) || status == -ENODEV) {
		adapt->bSurpriseRemoved = true;
	} else {
		struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
		haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
	}
}

And then just loops further. In case of 10 ENOMEM in a row,. passed pdata won't be initialized at all and driver doesn't do anything about it. I believe, it's not good approach to play with random values. We should somehow handle transfer errors all across the driver.

If I am missing something, please, let me know :)

With regards,
Pavel Skripkin

#18 lore raw
Quoted 5 lines · CEST Pavel Skripkin
Quoted 4 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I

decided

Quoted 1 line
Quoted 1 line
Quoted 1 line

to look at the code, because drivers in staging directory are always

buggy.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

The first thing I noticed is *no one* was checking read operations

result,

Quoted 4 lines
Quoted 4 lines

but

Quoted 1 line

it can fail and driver may start writing random stack values into

registers.

Quoted 6 lines
Quoted 6 lines

It

Quoted 1 line

can cause driver misbehavior or device misbehavior.

After the messages I wrote yesterday, I had some minutes to look deeper at

the

Quoted 3 lines
Quoted 3 lines

code that would be changed by these patches.

I think that it does not look like that the driver could return "random

stack

Quoted 3 lines
Quoted 3 lines

values into registers" and I think this entire series in unnecessary.

As far as I understand this driver (though I must admit that I really

don't

Quoted 1 line
Quoted 1 line

know how to write drivers, and I'm not interested in understanding - at

the

Quoted 1 line
Quoted 1 line

moment, at least), all the usb_read*() call usbctrl_vendorreq() and the

latter

Quoted 1 line
Quoted 1 line

*does* proper error checking before returning to the callers the read

data.

Quoted 2 lines
Quoted 2 lines

Please, look at the code copied from usbctrl_vendorreq() and pasted here

(some

Quoted 8 lines
Quoted 8 lines

comments are mine):

/* start of code */
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
{

/* test if everything is OK for transfers and setup the necessary

variables */

Quoted 6 lines
Quoted 6 lines

[...]

status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,

reqtype, value,

Quoted 7 lines
Quoted 7 lines

REALTEK_USB_VENQT_CMD_IDX,

pIo_buf, len,

RTW_USB_CONTROL_MSG_TIMEOUT);

                 if (status == len) {   /*  Success this control transfer. 

*/

Quoted 10 lines
Quoted 10 lines
                 
                         rtw_reset_continual_urb_error(dvobjpriv);
                         if (requesttype == 0x01)
                         
                                 memcpy(pdata, pIo_buf,  len); /* pdata

receives the read data */

	} else { /*  error cases */
Quoted 8 lines
Quoted 8 lines

[...]

}
/* end of code */

So, *I cannot ack this RFC*, unless maintainers say I'm missing something.

Larry, Philip, since you have much more knowledge than me about r8188eu

(and,

Quoted 1 line
Quoted 1 line

more in general, on device drivers) may you please say what you think

about my

Quoted 13 lines
Quoted 1 line

arguments against this series?

Hi, Fabio!

Thank you for looking into this, but I still can see the case when pdata won't be initialized:

pdata is initialized only in case of successful transfer, i.e len > 0. It means some data was received (maybe not full length, but anyway). In case of usb_control_msg() error (for example -ENOMEM) code only does this code block:

Quoted 6 lines
if (status < 0) {
	if (status == (-ESHUTDOWN) || status == -ENODEV) {
		adapt->bSurpriseRemoved = true;
	} else {
		struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
		haldata->srestpriv.Wifi_Error_Status = 

USB_VEN_REQ_CMD_FAIL;

Quoted 2 lines
	}
}

It's up to the callers of _rtw_usb*() to check return values and then act accordingly.

It doesn't matter whether or not *pdata is initialized because usb_read*() returns data = 0 if usb_control_msg() has not initialized/changed its third parameter. Then _rtw_read*() receive 0 or initialized data depending on errors or no errors. Finally _rtw_read*() returns that same value to the callers (via r_val).

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Furthermore, we have already either adapt->bSurpriseRemoved = true or haldata-

Quoted 1 line

srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL. Depending on contexts

where _rtw_read*() are called, perhaps they could also check the two variables above.

In summation. if anything should be changed, it is the code of the callers of _rtw_read*() if you find out they they don't properly handle the returning values of this function. You should find every place where _rtw_read*() are called and figure out if the returns are properly checked and handled; if not, make some change only there.

Larry, Philip, where are you? Am I missing something?

Thanks,

Fabio

Quoted 12 lines

And then just loops further. In case of 10 ENOMEM in a row,. passed pdata won't be initialized at all and driver doesn't do anything about it. I believe, it's not good approach to play with random values. We should somehow handle transfer errors all across the driver.

If I am missing something, please, let me know :)

With regards,
Pavel Skripkin

#19 lore raw
Quoted 2 lines · CEST Fabio M. De Francesco

It's up to the callers of _rtw_usb*() to check return values and then act accordingly.

Typo.

Replace "_rtw_usb*()" with "_rtw_read*()".

My fault. Sorry :(

Fabio

#20 lore raw
In reply to Fabio M. De Francesco
Quoted 111 lines · Fabio M. De Francesco
Quoted 5 lines · CEST Pavel Skripkin
Quoted 4 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I

decided

Quoted 1 line
Quoted 1 line
Quoted 1 line

to look at the code, because drivers in staging directory are always

buggy.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

The first thing I noticed is *no one* was checking read operations

result,

Quoted 4 lines
Quoted 4 lines

but

Quoted 1 line

it can fail and driver may start writing random stack values into

registers.

Quoted 6 lines
Quoted 6 lines

It

Quoted 1 line

can cause driver misbehavior or device misbehavior.

After the messages I wrote yesterday, I had some minutes to look deeper at

the

Quoted 3 lines
Quoted 3 lines

code that would be changed by these patches.

I think that it does not look like that the driver could return "random

stack

Quoted 3 lines
Quoted 3 lines

values into registers" and I think this entire series in unnecessary.

As far as I understand this driver (though I must admit that I really

don't

Quoted 1 line
Quoted 1 line

know how to write drivers, and I'm not interested in understanding - at

the

Quoted 1 line
Quoted 1 line

moment, at least), all the usb_read*() call usbctrl_vendorreq() and the

latter

Quoted 1 line
Quoted 1 line

*does* proper error checking before returning to the callers the read

data.

Quoted 2 lines
Quoted 2 lines

Please, look at the code copied from usbctrl_vendorreq() and pasted here

(some

Quoted 8 lines
Quoted 8 lines

comments are mine):

/* start of code */
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
{

/* test if everything is OK for transfers and setup the necessary

variables */

Quoted 6 lines
Quoted 6 lines

[...]

status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,

reqtype, value,

Quoted 7 lines
Quoted 7 lines

REALTEK_USB_VENQT_CMD_IDX,

pIo_buf, len,

RTW_USB_CONTROL_MSG_TIMEOUT);

                 if (status == len) {   /*  Success this control transfer. 

*/

Quoted 10 lines
Quoted 10 lines
                 
                         rtw_reset_continual_urb_error(dvobjpriv);
                         if (requesttype == 0x01)
                         
                                 memcpy(pdata, pIo_buf,  len); /* pdata

receives the read data */

	} else { /*  error cases */
Quoted 8 lines
Quoted 8 lines

[...]

}
/* end of code */

So, *I cannot ack this RFC*, unless maintainers say I'm missing something.

Larry, Philip, since you have much more knowledge than me about r8188eu

(and,

Quoted 1 line
Quoted 1 line

more in general, on device drivers) may you please say what you think

about my

Quoted 13 lines
Quoted 1 line

arguments against this series?

Hi, Fabio!

Thank you for looking into this, but I still can see the case when pdata won't be initialized:

pdata is initialized only in case of successful transfer, i.e len > 0. It means some data was received (maybe not full length, but anyway). In case of usb_control_msg() error (for example -ENOMEM) code only does this code block:

Quoted 6 lines
if (status < 0) {
	if (status == (-ESHUTDOWN) || status == -ENODEV) {
		adapt->bSurpriseRemoved = true;
	} else {
		struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
		haldata->srestpriv.Wifi_Error_Status = 

USB_VEN_REQ_CMD_FAIL;

Quoted 2 lines
	}
}

It's up to the callers of _rtw_usb*() to check return values and then act accordingly.

Quoted 9 lines

It doesn't matter whether or not *pdata is initialized because usb_read*() returns data = 0 if usb_control_msg() has not initialized/changed its third parameter. Then _rtw_read*() receive 0 or initialized data depending on errors or no errors. Finally _rtw_read*() returns that same value to the callers (via r_val).

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:

1. Error on transfer side
2. Actual register value is 0

Quoted 4 lines

Furthermore, we have already either adapt->bSurpriseRemoved = true or haldata-

Quoted 1 line

srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL. Depending on contexts

where _rtw_read*() are called, perhaps they could also check the two variables above.

Yes, Wifi_Error_Status can be used, but it's set every time an error occurred. For example if 8th usb_control_msg() was successful Wifi_Error_Status will be set to error anyway. It's can be easily fixed, of course.

IMO, we should switch to standard way of handling these type of errors to move the driver out of staging someday

BTW: syzbot already found uninit value bug in r817xu driver:

https://syzkaller.appspot.com/bug?id=3cd92b1d85428b128503bfa7a250294c9ae00bd8

The usb related code in these drivers is the same, so bugs I am talking about are real.

Quoted 9 lines

In summation. if anything should be changed, it is the code of the callers of _rtw_read*() if you find out they they don't properly handle the returning values of this function. You should find every place where _rtw_read*() are called and figure out if the returns are properly checked and handled; if not, make some change only there.

Larry, Philip, where are you? Am I missing something?

I am waiting for their replies too :) I have almost ready v2, so...

With regards,
Pavel Skripkin

maintainer
#21 lore raw
Quoted 110 lines · Pavel Skripkin
Quoted 109 lines · Fabio M. De Francesco
Quoted 5 lines · CEST Pavel Skripkin
Quoted 3 lines · Fabio M. De Francesco
Quoted 2 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

Quoted 1 line
Quoted 1 line

I noticed, that new staging driver was added like 3 weeks ago

and I

decided

Quoted 2 lines
Quoted 1 line
Quoted 1 line

to look at the code, because drivers in staging directory are

always

buggy.

Quoted 2 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

The first thing I noticed is *no one* was checking read

operations

result,

Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

but

Quoted 1 line

it can fail and driver may start writing random stack values

into

registers.

Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

It

Quoted 1 line

can cause driver misbehavior or device misbehavior.

After the messages I wrote yesterday, I had some minutes to look

deeper at

the

Quoted 3 lines
Quoted 2 lines

code that would be changed by these patches.

Quoted 1 line

I think that it does not look like that the driver could return

"random

stack

Quoted 3 lines
Quoted 2 lines

values into registers" and I think this entire series in unnecessary.

Quoted 1 line

As far as I understand this driver (though I must admit that I

really

don't

Quoted 2 lines
Quoted 1 line

know how to write drivers, and I'm not interested in understanding

- at

the

Quoted 2 lines
Quoted 1 line

moment, at least), all the usb_read*() call usbctrl_vendorreq()

and the

latter

Quoted 2 lines
Quoted 1 line

*does* proper error checking before returning to the callers the

read

data.

Quoted 2 lines
Quoted 1 line
Quoted 1 line

Please, look at the code copied from usbctrl_vendorreq() and

pasted here

(some

Quoted 7 lines
Quoted 6 lines

comments are mine):

Quoted 1 line

/* start of code */

static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata, u16 len, u8 requesttype)
{

Quoted 1 line

/* test if everything is OK for transfers and setup the

necessary

variables */

Quoted 8 lines
Quoted 7 lines

[...]

Quoted 6 lines

status = usb_control_msg(udev, pipe, REALTEK_USB_VENQT_CMD_REQ,
reqtype, value,
REALTEK_USB_VENQT_CMD_IDX,
pIo_buf, len,

RTW_USB_CONTROL_MSG_TIMEOUT);
                 if (status == len) {   /*  Success this control

transfer.

*/

Quoted 9 lines
Quoted 1 line
                 >

rtw_reset_continual_urb_error(dvobjpriv);

Quoted 2 lines
                         if (requesttype == 0x01)
                         >

memcpy(pdata, pIo_buf, len); /* pdata

Quoted 4 lines
Quoted 4 lines

receives the read data */

	} else { /*  error cases */

[...]
}

Quoted 5 lines
Quoted 2 lines

/* end of code */

Quoted 1 line

So, *I cannot ack this RFC*, unless maintainers say I'm missing

something.

Quoted 1 line
Quoted 1 line

Larry, Philip, since you have much more knowledge than me about

r8188eu

(and,

Quoted 2 lines
Quoted 1 line

more in general, on device drivers) may you please say what you

think

about my

Quoted 13 lines
Quoted 1 line

arguments against this series?

Hi, Fabio!

Thank you for looking into this, but I still can see the case when pdata won't be initialized:

pdata is initialized only in case of successful transfer, i.e len > 0. It means some data was received (maybe not full length, but anyway). In case of usb_control_msg() error (for example -ENOMEM) code only does this code block:

Quoted 6 lines
if (status < 0) {
	if (status == (-ESHUTDOWN) || status == -ENODEV) {
		adapt->bSurpriseRemoved = true;
	} else {
		struct hal_data_8188e	*haldata = GET_HAL_DATA(adapt);
		haldata->srestpriv.Wifi_Error_Status =

USB_VEN_REQ_CMD_FAIL;

Quoted 2 lines
	}
}

It's up to the callers of _rtw_usb*() to check return values and then act accordingly.

It doesn't matter whether or not *pdata is initialized because usb_read*() returns data = 0 if usb_control_msg() has not initialized/changed its third parameter. Then _rtw_read*() receive 0 or initialized data depending on errors or no errors. Finally _rtw_read*() returns that same value to the callers (via r_val).

Quoted 8 lines
Quoted 3 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:

1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

Quoted 7 lines
Quoted 7 lines

In summation. if anything should be changed, it is the code of the callers of _rtw_read*() if you find out they they don't properly handle the returning values of this function. You should find every place where _rtw_read*() are called and figure out if the returns are properly checked and handled; if not, make some change only there.

Larry, Philip, where are you? Am I missing something?

Relax, there is no need to get jumpy, people do not have to respond instantly to emails here. Especially when it is not their job to do so.

greg k-h

#22 lore raw
Quoted 10 lines · Greg KH
Quoted 5 lines

Yes, but _rtw_read*() == 0 indicates 2 states:

1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

Thank you, Greg, for confirmation. That's was the point why I started to write this series :)

I think, usb_control_msg_recv() won't help us with this problem, since all rtw_read*() functions return an unsigned value now. In future, when driver code will be fixed (ex: a lot of void function, which can fail and leave passed pointer uninitialized) we can move to new usb API and then move driver out of staging :)

With regards,
Pavel Skripkin

maintainer
#23 lore raw
Quoted 12 lines · Pavel Skripkin
Quoted 10 lines · Greg KH
Quoted 5 lines

Yes, but _rtw_read*() == 0 indicates 2 states:

1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

Quoted 8 lines

Thank you, Greg, for confirmation. That's was the point why I started to write this series :)

I think, usb_control_msg_recv() won't help us with this problem, since all rtw_read*() functions return an unsigned value now. In future, when driver code will be fixed (ex: a lot of void function, which can fail and leave passed pointer uninitialized) we can move to new usb API and then move driver out of staging :)

That function _should_ be used at the lower levels of this call chain. If you want to go from the top -> down or bottom -> up of fixing this is your choice, but as others have pointed out, this patch series as-is still needs some work.

thanks,

greg k-h

#24 lore raw
In reply to Greg KH
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 10 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

Quoted 1 line
Quoted 1 line
Quoted 1 line

In summation. if anything should be changed, it is the code of the

callers of

Quoted 1 line
Quoted 1 line
Quoted 1 line

_rtw_read*() if you find out they they don't properly handle the

returning

Quoted 1 line
Quoted 1 line
Quoted 1 line

values of this function. You should find every place where _rtw_read*()

are

Quoted 1 line
Quoted 1 line
Quoted 1 line

called and figure out if the returns are properly checked and handled;

if not,

Quoted 6 lines
Quoted 3 lines
Quoted 3 lines

make some change only there.

Larry, Philip, where are you? Am I missing something?

Relax, there is no need to get jumpy, people do not have to respond instantly to emails here. Especially when it is not their job to do so.

I should have placed a big smile at the end of the phrase. I was just kidding while trying to get their attention. I know there is no hurry and that no one has any obligation of this kind. Again, just kidding :)

Thanks,

Fabio

Quoted 1 line

greg k-h

maintainer
#25 lore raw
Quoted 12 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

Quoted 7 lines
Quoted 3 lines

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

Fix what specifically here? The usb_control_msg() call? If so, that is why usb_control_msg_recv() was created, as sometimes you do want to do what usb_control_msg() does today (see the users in the USB core today for examples of why this is needed.)

In general, yes, 0 is success, negative is error, and positive is the number of bytes read/written.

Anyway, let's see the second round of patches here before continuing this thread...

thanks,

greg k-h

#26 lore raw
In reply to Fabio M. De Francesco
Quoted 12 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

Quoted 8 lines
Quoted 3 lines

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

That's what I've done in v2. All rtw_read* family will have following prototype in v2:

int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);

Was it your idea, or you were talking about different approach?

With regards,
Pavel Skripkin

#27 lore raw

v2 cover staging: r8188eu: avoid uninit value bugs

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  57 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1138 insertions(+), 389 deletions(-)
Signature · 1 line
2.32.0
#28 lore raw

RFC PATCH v2 1/6 staging: r8188eu: remove {read,write}_macreg

These 2 functions are unused, so they can be simply removed

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 39 ------------------------
 drivers/staging/r8188eu/include/rtw_mp.h |  2 --
 2 files changed, 41 deletions(-)
drivers/staging/r8188eu/core/rtw_mp.c +0 -39
index 93bb683b628f..0a0a24fd37b0 100644
@@ -7,45 +7,6 @@
 #include "../include/odm_precomp.h"
 #include "../include/rtl8188e_hal.h"
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
-{
-	u32 val = 0;
-
-	switch (sz) {
-	case 1:
-		val = rtw_read8(padapter, addr);
-		break;
-	case 2:
-		val = rtw_read16(padapter, addr);
-		break;
-	case 4:
-		val = rtw_read32(padapter, addr);
-		break;
-	default:
-		val = 0xffffffff;
-		break;
-	}
-
-	return val;
-}
-
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz)
-{
-	switch (sz) {
-	case 1:
-		rtw_write8(padapter, addr, (u8)val);
-		break;
-	case 2:
-		rtw_write16(padapter, addr, (u16)val);
-		break;
-	case 4:
-		rtw_write32(padapter, addr, val);
-		break;
-	default:
-		break;
-	}
-}
-
 u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask)
 {
 	return rtw_hal_read_bbreg(padapter, addr, bitmask);
drivers/staging/r8188eu/include/rtw_mp.h +0 -2
index b64b16554343..3a259d991348 100644
@@ -410,8 +410,6 @@ void mp_stop_test(struct adapter *padapter);
 u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask);
 void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val);
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
 u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
 void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
 u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
Signature · 1 line
2.32.0
#29 lore raw

RFC PATCH v2 2/6 staging: r8188eu: add helper macro for printing registers

In reply to Pavel Skripkin

There are a lof of places, where DBG_88E() is used to print register value. Since following patches change _rtw_read*() family prototypes, we can wrap printing registers into useful macro to avoid open-coding error checking like this:

	u32 tmp;
	if (!rtw_read(&tmp))
		DBG("reg = %d\n", tmp);

So, added DBG_88E_REG{8,16,32} macros for printing register values.

---
 drivers/staging/r8188eu/include/rtw_debug.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
drivers/staging/r8188eu/include/rtw_debug.h +13 -0
index 3c3bf2a4f30e..059647b9cd3a 100644
@@ -72,6 +72,19 @@ extern u32 GlobalDebugLevel;
 			pr_info(DRIVER_PREFIX __VA_ARGS__);			\
 	} while (0)
 
+#define __DBG_88E_REG(fmt, adap, reg, size)				\
+	do {								\
+		u##size __tmp__;					\
+		if (rtw_read##size((adap), (reg), &__tmp__))		\
+			break;						\
+		if (_drv_err_ <= GlobalDebugLevel)			\
+			pr_info(DRIVER_PREFIX fmt, __tmp__);		\
+	} while (0)
+
+#define DBG_88E_REG8(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 8)
+#define DBG_88E_REG16(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 16)
+#define DBG_88E_REG32(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 32)
+
 int proc_get_drv_version(char *page, char **start,
 			 off_t offset, int count,
 			 int *eof, void *data);
Signature · 1 line
2.32.0
#30 lore raw

RFC PATCH v2 3/6 staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  11 +-
 drivers/staging/r8188eu/core/rtw_efuse.c      |  76 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |   9 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  13 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |   5 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  19 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |   4 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 ++-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 128 +++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  10 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |   8 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 267 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  19 +-
 .../staging/r8188eu/include/odm_interface.h   |   2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |   6 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  |  61 +++-
 20 files changed, 569 insertions(+), 158 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +8 -3
index 2ee64cef73f7..8b7d3eb12bd0 100644
@@ -73,8 +73,8 @@ int proc_get_read_reg(char *page, char **start,
 {
 	struct net_device *dev = data;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
-	int len = 0;
+	u32 tmp;
+	int len = 0, error;
 
 	if (proc_get_read_addr == 0xeeeeeeee) {
 		*eof = 1;
@@ -83,7 +83,12 @@ int proc_get_read_reg(char *page, char **start,
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		error = rtw_read8(padapter, proc_get_read_addr, (u8 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
 		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_efuse.c +60 -16

153 lines not on this page · raw message

drivers/staging/r8188eu/core/rtw_io.c +3 -6
index cde0205816b1..2714506c8ffb 100644
@@ -34,18 +34,15 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 {
-	u8 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl *pintfhdl = &pio_priv->intf;
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-
+	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 
 	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
 
-	return r_val;
+	return _read8(pintfhdl, addr, data);
 }
 
 u16 _rtw_read16(struct adapter *adapter, u32 addr)
drivers/staging/r8188eu/core/rtw_mp.c +11 -2
index 0a0a24fd37b0..76f0bc399819 100644
@@ -243,10 +243,14 @@ void GetPowerTracking(struct adapter *padapter, u8 *enable)
 static void disable_dm(struct adapter *padapter)
 {
 	u8 v8;
+	int error;
 
 	/* 3 1. disable firmware dynamic mechanism */
 	/*  disable Power Training, Rate Adaptive */
-	v8 = rtw_read8(padapter, REG_BCN_CTRL);
+	error = rtw_read8(padapter, REG_BCN_CTRL, &v8);
+	if (error)
+		return;
+
 	v8 &= ~EN_BCN_FUNCTION;
 	rtw_write8(padapter, REG_BCN_CTRL, v8);
 
@@ -363,8 +367,13 @@ s32 mp_start_test(struct adapter *padapter)
 	spin_unlock_bh(&pmlmepriv->lock);
 
 	if (res == _SUCCESS) {
+		int error;
 		/*  set MSR to WIFI_FW_ADHOC_STATE */
-		val8 = rtw_read8(padapter, MSR) & 0xFC; /*  0x0102 */
+		error = rtw_read8(padapter, MSR, &val8); /*  0x0102 */
+		if (error)
+			return _FAIL;
+
+		val8 &= 0xFC;
 		val8 |= WIFI_FW_ADHOC_STATE;
 		rtw_write8(padapter, MSR, val8); /*  Link in ad hoc network */
 	}
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +4 -1
index c85f8e467337..894ab456f202 100644
@@ -632,6 +632,7 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 	u32		offset, width;
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+	int error;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -647,7 +648,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 
 	switch (width) {
 	case 1:
-		RegRWStruct->value = rtw_read8(Adapter, offset);
+		error = rtw_read8(Adapter, offset, (u8 *) &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	case 2:
 		RegRWStruct->value = rtw_read16(Adapter, offset);
drivers/staging/r8188eu/hal/HalPhyRf_8188e.c +16 -3
index 356885e27edd..3545ad60dc00 100644
@@ -660,8 +660,12 @@ static void _PHY_SaveMACRegisters(
 	u32 i;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+	int error;
+
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		MACBackup[i] = ODM_Read1Byte(dm_odm, MACReg[i]);
+		error = ODM_Read1Byte(dm_odm, MACReg[i], (u8 *) &MACBackup[i]);
+		if (error)
+			return;
 	}
 	MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
 }
@@ -1010,9 +1014,12 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
 	u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+	int error;
 
 	/* Check continuous TX and Packet TX */
-	tmpreg = ODM_Read1Byte(dm_odm, 0xd03);
+	error = ODM_Read1Byte(dm_odm, 0xd03, &tmpreg);
+	if (error)
+		return;
 
 	if ((tmpreg & 0x70) != 0)			/* Deal with contisuous TX case */
 		ODM_Write1Byte(dm_odm, 0xd03, tmpreg & 0x8F);	/* disable all continuous TX */
@@ -1232,7 +1239,13 @@ static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2
 
 	if (!adapt->hw_init_completed) {
 		u8 u1btmp;
-		u1btmp = ODM_Read1Byte(dm_odm, REG_LEDCFG2) | BIT(7);
+		int error;
+
+		error = ODM_Read1Byte(dm_odm, REG_LEDCFG2, &u1btmp);
+		if (error)
+			return;
+
+		u1btmp |= BIT(7);
 		ODM_Write1Byte(dm_odm, REG_LEDCFG2, u1btmp);
 		ODM_SetBBReg(dm_odm, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
 	}
drivers/staging/r8188eu/hal/HalPwrSeqCmd.c +7 -2
index 0fd11aca7ac7..74e83381ef06 100644
@@ -35,6 +35,7 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 	u32 offset = 0;
 	u32 poll_count = 0; /*  polling autoload done. */
 	u32 max_poll_count = 5000;
+	int error;
 
 	do {
 		pwrcfgcmd = pwrseqcmd[aryidx];
@@ -48,7 +49,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 
 				/*  Read the value from system register */
-				value = rtw_read8(padapter, offset);
+				error = rtw_read8(padapter, offset, &value);
+				if (error)
+					return false;
 
 				value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
 				value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
@@ -60,7 +63,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				poll_bit = false;
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 				do {
-					value = rtw_read8(padapter, offset);
+					error = rtw_read8(padapter, offset, &value);
+					if (error)
+						return false;
 
 					value &= GET_PWR_CFG_MASK(pwrcfgcmd);
 					if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
drivers/staging/r8188eu/hal/hal_com.c +17 -6
index f09d4d49b159..833c88c85e3f 100644
@@ -321,11 +321,14 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 	struct c2h_evt_hdr *c2h_evt;
 	int i;
 	u8 trigger;
+	int error;
 
 	if (!buf)
 		goto exit;
 
-	trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
+	error = rtw_read8(adapter, REG_C2HEVT_CLEAR, &trigger);
+	if (error)
+		goto exit;
 
 	if (trigger == C2H_EVT_HOST_CLOSE)
 		goto exit; /* Not ready */
@@ -336,13 +339,21 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 
 	memset(c2h_evt, 0, 16);
 
-	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
-	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
+	error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, buf);
+	if (error)
+		goto clear_evt;
+
+	error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, buf + 1);
+	if (error)
+		goto clear_evt;
 
 	/* Read the content */
-	for (i = 0; i < c2h_evt->plen; i++)
-		c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
-						sizeof(*c2h_evt) + i);
+	for (i = 0; i < c2h_evt->plen; i++) {
+		error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + sizeof(*c2h_evt) + i,
+				  c2h_evt->payload + i);
+		if (error)
+			goto clear_evt;
+	}
 
 	ret = _SUCCESS;
 
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 5a01495d74bc..9a9df98da727 100644
@@ -4,10 +4,10 @@
 #include "../include/odm_precomp.h"
 /*  ODM IO Relative API. */
 
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read8(Adapter, RegAddr);
+	return rtw_read8(Adapter, RegAddr, data);
 }
 
 u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
drivers/staging/r8188eu/hal/rtl8188e_cmd.c +25 -8
index 3e1a45030bc8..53636c0e4786 100644
@@ -21,12 +21,14 @@ static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
 {
 	u8 read_down = false;
 	int	retry_cnts = 100;
-
+	int error;
 	u8 valid;
 
 	do {
-		valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
-		if (0 == valid)
+		error = rtw_read8(adapt, REG_HMETFR, &valid);
+		if (error)
+			return read_down;
+		else if (!(valid & BIT(msgbox_num)))
 			read_down = true;
 	} while ((!read_down) && (retry_cnts--));
 
@@ -578,8 +580,9 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
 	bool	bSendBeacon = false;
 	bool	bcn_valid = false;
-	u8 DLBcnCount = 0;
+	u8 DLBcnCount = 0, val8;
 	u32 poll = 0;
+	int error;
 
 	DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
 
@@ -596,8 +599,15 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  Disable Hw protection for a time which revserd for Hw sending beacon. */
 		/*  Fix download reserved page packet fail that access collision with the protection time. */
 		/*  2010.05.11. Added by tynli. */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(3)));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(4));
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 & (~BIT(3)));
+
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 | BIT(4));
 
 		if (haldata->RegFwHwTxQCtrl & BIT(6)) {
 			DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
@@ -639,8 +649,15 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  */
 
 		/*  Enable Bcn */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(3));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(4)));
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 | BIT(3));
+
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 & (~BIT(4)));
 
 		/*  To make sure that if there exists an adapter which would like to send beacon. */
 		/*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
drivers/staging/r8188eu/hal/rtl8188e_dm.c +5 -1
index 78552303c990..5cb3d6369449 100644
@@ -16,8 +16,12 @@ static void dm_CheckStatistics(struct adapter *Adapter)
 static void dm_InitGPIOSetting(struct adapter *Adapter)
 {
 	u8	tmp1byte;
+	int error;
+
+	error = rtw_read8(Adapter, REG_GPIO_MUXCFG, &tmp1byte);
+	if (error)
+		return;
 
-	tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
 	tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
 
 	rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +99 -29

256 lines not on this page · raw message

drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +8 -2
index 30a9dca8f453..f6d4c91a97a2 100644
@@ -960,6 +960,7 @@ _PHY_SetBWMode92C(
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
 	u8 regBwOpMode;
 	u8 regRRSR_RSC;
+	int error;
 
 	if (pHalData->rf_chip == RF_PSEUDO_11N)
 		return;
@@ -975,8 +976,13 @@ _PHY_SetBWMode92C(
 	/* 3<1>Set MAC register */
 	/* 3 */
 
-	regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
-	regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2);
+	error = rtw_read8(Adapter, REG_BWOPMODE, &regBwOpMode);
+	if (error)
+		return;
+
+	error = rtw_read8(Adapter, REG_RRSR + 2, &regRRSR_RSC);
+	if (error)
+		return;
 
 	switch (pHalData->CurrentChannelBW) {
 	case HT_CHANNEL_WIDTH_20:
drivers/staging/r8188eu/hal/rtl8188e_sreset.c +6 -2
index 16fa249e35d3..39dacfb23570 100644
@@ -49,13 +49,17 @@ void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
 {
 	u32 rx_dma_status = 0;
 	u8 fw_status = 0;
+	int error;
+
 	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
 	if (rx_dma_status != 0x00) {
 		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
 	}
-	fw_status = rtw_read8(padapter, REG_FMETHR);
-	if (fw_status != 0x00) {
+	error = rtw_read8(padapter, REG_FMETHR, &fw_status);
+	if (error) {
+		return;
+	} else if (fw_status != 0x00) {
 		if (fw_status == 1)
 			DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
 		else if (fw_status == 2)
drivers/staging/r8188eu/hal/rtl8188eu_led.c +15 -3
index 452d4bb87aba..7f793b7ce609 100644
@@ -14,10 +14,15 @@
 void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return;
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);
+
+	error = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);
+	if (error)
+		return;
+
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
 		rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /*  SW control led0 on. */
@@ -37,11 +42,14 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		goto exit;
 
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
+	error = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);/* 0x4E */
+	if (error)
+		return;
 
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
@@ -49,7 +57,11 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 			/*  Open-drain arrangement for controlling the LED) */
 			LedCfg &= 0x90; /*  Set to software control. */
 			rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
-			LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
+
+			error = rtw_read8(padapter, REG_MAC_PINMUX_CFG, &LedCfg);
+			if (error)
+				return;
+
 			LedCfg &= 0xFE;
 			rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
 		} else {
drivers/staging/r8188eu/hal/usb_halinit.c +220 -47

540 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_ops_linux.c +11 -8
index 953fa05dc30c..380d126c8b2f 100644
@@ -101,26 +101,29 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata,
 	return status;
 }
 
-static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	u8 data = 0;
-
+	int res;
 
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 1;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
-
-
-
-	return data;
+	res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);
+	if (res < 0)
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 8 bytes: %d\n", res);
+	else
+		/* Noone cares about positive return value */
+		res = 0;
 
+	return res;
 }
 
 static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 6b589413d56c..8e531d272927 100644
@@ -60,7 +60,7 @@ typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
 
 /*  =========== EXtern Function Prototype */
 
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
 u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index f1b3074fa075..fd99b36abca6 100644
@@ -85,7 +85,7 @@ struct intf_hdl;
 struct io_queue;
 
 struct _io_ops {
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
 	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
@@ -248,7 +248,7 @@ void unregister_intf_hdl(struct intf_hdl *pintfhdl);
 void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
 u16 _rtw_read16(struct adapter *adapter, u32 addr);
 u32 _rtw_read32(struct adapter *adapter, u32 addr);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
@@ -270,7 +270,7 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
 			     u8 *pmem, int timeout_ms);
 void _rtw_write_port_cancel(struct adapter *adapter);
 
-#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr))
+#define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
 #define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
 #define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
drivers/staging/r8188eu/os_dep/ioctl_linux.c +48 -13

147 lines not on this page · raw message

Signature · 1 line
2.32.0
#32 lore raw

RFC PATCH v2 4/6 staging: r8188eu: add error handling of rtw_read16

In reply to Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  7 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  9 ++---
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  4 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 29 +++++++++++----
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  5 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 37 ++++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 19 ++++++++--
 .../staging/r8188eu/include/odm_interface.h   |  2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  6 +--
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 28 +++++++++++---
 11 files changed, 112 insertions(+), 38 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
index 8b7d3eb12bd0..a41675e101ac 100644
@@ -91,7 +91,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		error = rtw_read16(padapter, proc_get_read_addr, (u16 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n",
+				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
 		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_io.c +3 -6
index 2714506c8ffb..fd64893c778d 100644
@@ -45,18 +45,15 @@ int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 	return _read8(pintfhdl, addr, data);
 }
 
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 {
-	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 
 	_read16 = pintfhdl->io_ops._read16;
 
-	r_val = _read16(pintfhdl, addr);
-
-	return r_val;
+	return _read16(pintfhdl, addr, data);
 }
 
 u32 _rtw_read32(struct adapter *adapter, u32 addr)
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +3 -1
index 894ab456f202..c6f7636c2174 100644
@@ -653,7 +653,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	case 2:
-		RegRWStruct->value = rtw_read16(Adapter, offset);
+		error = rtw_read16(Adapter, offset, (u16 *) &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	default:
 		width = 4;
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 9a9df98da727..669d3e5eafb6 100644
@@ -10,10 +10,10 @@ int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data)
 	return rtw_read8(Adapter, RegAddr, data);
 }
 
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read16(Adapter, RegAddr);
+	return rtw_read16(Adapter, RegAddr, data);
 }
 
 u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +21 -8
index cfc429965b7d..94e2828c328e 100644
@@ -262,7 +262,11 @@ static void efuse_read_phymap_from_txpktbuf(
 			 * do not remove it as the rtw_read16() call consumes
 			 * 2 bytes from the EEPROM source.
 			 */
-			u16 lenc = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
+			u16 lenc;
+
+			error = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, &lenc);
+			if (error)
+				return;
 
 			len = le32_to_cpu(lo32) & 0x0000ffff;
 
@@ -778,21 +782,27 @@ hal_EfusePowerSwitch_RTL8188E(
 		rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
 
 		/*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
-		if (!(tmpV16 & PWC_EV12V)) {
+		error = rtw_read16(pAdapter, REG_SYS_ISO_CTRL, &tmpV16);
+		if (error) {
+			return;
+		} else if (!(tmpV16 & PWC_EV12V)) {
 			tmpV16 |= PWC_EV12V;
 			rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
 		}
 		/*  Reset: 0x0000h[28], default valid */
-		tmpV16 =  rtw_read16(pAdapter, REG_SYS_FUNC_EN);
-		if (!(tmpV16 & FEN_ELDR)) {
+		error = rtw_read16(pAdapter, REG_SYS_FUNC_EN, &tmpV16);
+		if (error) {
+			return;
+		} else if (!(tmpV16 & FEN_ELDR)) {
 			tmpV16 |= FEN_ELDR;
 			rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
 		}
 
 		/*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
-		if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
+		error = rtw_read16(pAdapter, REG_SYS_CLKR, &tmpV16);
+		if (error) {
+			return;
+		} else if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
 			tmpV16 |= (LOADER_CLK_EN | ANA8M);
 			rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
 		}
@@ -1915,8 +1925,11 @@ u8 GetEEPROMSize8188E(struct adapter *padapter)
 {
 	u8 size = 0;
 	u32	cr;
+	int error;
 
-	cr = rtw_read16(padapter, REG_9346CR);
+	error = rtw_read16(padapter, REG_9346CR, (u16 *) &cr);
+	if (error)
+		return size;
 	/*  6: EEPROM used is 93C46, 4: boot from E-Fuse. */
 	size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
 
drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +4 -1
index f6d4c91a97a2..3afb66195413 100644
@@ -577,11 +577,14 @@ PHY_BBConfig8188E(
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(Adapter);
 	u32 RegVal;
 	u8 CrystalCap;
+	int error;
 
 	phy_InitBBRFRegisterDefinition(Adapter);
 
 	/*  Enable BB and RF */
-	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+	error = rtw_read16(Adapter, REG_SYS_FUNC_EN, (u16 *) &RegVal);
+	if (error)
+		return _FAIL;
 	rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1)));
 
 	/*  20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
drivers/staging/r8188eu/hal/usb_halinit.c +32 -5
index 4f1d7f9b43c3..4ecccc6499aa 100644
@@ -90,6 +90,8 @@ static u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
 	u16 value16;
 	/*  HW Power on sequence */
 	struct hal_data_8188e	*haldata	= GET_HAL_DATA(adapt);
+	int error;
+
 	if (haldata->bMacPwrCtrlOn)
 		return _SUCCESS;
 
@@ -103,7 +105,10 @@ static u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
 	rtw_write16(adapt, REG_CR, 0x00);  /* suggseted by zhouzhou, by page, 20111230 */
 
 		/*  Enable MAC DMA/WMAC/SCHEDULE/SEC block */
-	value16 = rtw_read16(adapt, REG_CR);
+	error = rtw_read16(adapt, REG_CR, &value16);
+	if (error)
+		return _FAIL;
+
 	value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
 				| PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
 	/*  for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
@@ -207,7 +212,14 @@ static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
 				       u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
 				       u16 hiQ)
 {
-	u16 value16	= (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+	u16 value16;
+	int error;
+
+	error = rtw_read16(Adapter, REG_TRXDMA_CTRL, &value16);
+	if (error)
+		return;
+
+	value16 &= 0x7;
 
 	value16 |= _TXDMA_BEQ_MAP(beQ)	| _TXDMA_BKQ_MAP(bkQ) |
 		   _TXDMA_VIQ_MAP(viQ)	| _TXDMA_VOQ_MAP(voQ) |
@@ -868,7 +880,12 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 	/*  Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
 	/*  */
 	/*  Enable MACTXEN/MACRXEN block */
-	value16 = rtw_read16(Adapter, REG_CR);
+	error = rtw_read16(Adapter, REG_CR, &value16);
+	if (error) {
+		status = _FAIL;
+		goto exit;
+	}
+
 	value16 |= (MACTXEN | MACRXEN);
 	rtw_write8(Adapter, REG_CR, value16);
 
@@ -937,6 +954,8 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 		Adapter->mppriv.channel = haldata->CurrentChannel;
 		MPT_InitializeAdapter(Adapter, Adapter->mppriv.channel);
 	} else {
+		u16 val16;
+
 		/*  2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
 		/*  and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
 		/*  call initstruct adapter. May cause some problem?? */
@@ -956,7 +975,13 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 		rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
 
 		/* enable tx DMA to drop the redundate data of packet */
-		rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+		error = rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK, &val16);
+		if (error) {
+			status = _FAIL;
+			goto exit;
+		}
+
+		rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (val16 | DROP_DATA_EN));
 
 		HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
 		/*  2010/08/26 MH Merge from 8192CE. */
@@ -1982,7 +2007,9 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 			rtw_write8(Adapter, REG_TXPAUSE, 0xff);
 
 			/* keep sn */
-			Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
+			error = rtw_read16(Adapter, REG_NQOS_SEQ, &Adapter->xmitpriv.nqos_ssn);
+			if (error)
+				return;
 
 			if (!pwrpriv->bkeepfwalive) {
 				/* RX DMA stop */
drivers/staging/r8188eu/hal/usb_ops_linux.c +15 -4
index 380d126c8b2f..58e852555f54 100644
@@ -126,19 +126,30 @@ static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data)
 	return res;
 }
 
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 2;
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 16 bytes: %d\n", res);
+	} else {
+		/* Noone cares about positive return value */
+		*data = le32_to_cpu(tmp) & 0xffff;
+		res = 0;
+	}
 
-	return (u16)(le32_to_cpu(data) & 0xffff);
+	return res;
 }
 
 static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 8e531d272927..2455dae6eebb 100644
@@ -62,7 +62,7 @@ typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
 
 int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data);
 
 u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index fd99b36abca6..c44554c848cf 100644
@@ -86,7 +86,7 @@ struct io_queue;
 
 struct _io_ops {
 	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
@@ -249,7 +249,7 @@ void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
 int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
-u16 _rtw_read16(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data);
 u32 _rtw_read32(struct adapter *adapter, u32 addr);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
@@ -271,7 +271,7 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
 void _rtw_write_port_cancel(struct adapter *adapter);
 
 #define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
-#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
+#define rtw_read16(adapter, addr, data) _rtw_read16((adapter), (addr), (data))
 #define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
 	_rtw_read_mem((adapter), (addr), (cnt), (mem))
drivers/staging/r8188eu/os_dep/ioctl_linux.c +22 -6
index c9f0772bcbe1..79f0fbaa841e 100644
@@ -2101,7 +2101,10 @@ static int rtw_wx_read32(struct net_device *dev,
 		sprintf(extra, "0x%02X", data32);
 		break;
 	case 2:
-		data32 = rtw_read16(padapter, addr);
+		error = rtw_read16(padapter, addr, (u16 *) &data32);
+		if (error)
+			return error;
+
 		sprintf(extra, "0x%04X", data32);
 		break;
 	case 4:
@@ -2271,7 +2274,8 @@ static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 le
 					 (u8 *) &RegRWStruct->value);
 			break;
 		case 2:
-			RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
+			error = rtw_read16(padapter, RegRWStruct->offset,
+					  (u16 *) &RegRWStruct->value);
 			break;
 		case 4:
 			RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
@@ -3990,7 +3994,8 @@ static int rtw_dbg_port(struct net_device *dev,
 				DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, (u8) tmp);
 			break;
 		case 2:
-			DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+			if (!rtw_read16(padapter, arg, (u16 *) &tmp))
+				DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, (u16) tmp);
 			break;
 		case 4:
 			DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
@@ -4006,8 +4011,12 @@ static int rtw_dbg_port(struct net_device *dev,
 
 			break;
 		case 2:
+			error = rtw_read16(padapter, arg, (u16 *) &tmp);
+			if (error)
+				return error;
+
 			rtw_write16(padapter, arg, extra_arg);
-			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, (u16) tmp);
 			break;
 		case 4:
 			rtw_write32(padapter, arg, extra_arg);
@@ -4138,7 +4147,10 @@ static int rtw_dbg_port(struct net_device *dev,
 			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
 				ret = -EPERM;
 
-			final = rtw_read16(padapter, reg);
+			error = rtw_read16(padapter, reg, &final);
+			if (error)
+				return error;
+
 			if (start_value + write_num - 1 == final)
 				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
 			else
@@ -5387,7 +5399,11 @@ static int rtw_mp_read_reg(struct net_device *dev,
 		break;
 	case 'w':
 		/*  2 bytes */
-		sprintf(data, "%04x\n", rtw_read16(padapter, addr));
+		error = rtw_read16(padapter, addr, (u16 *) &val32);
+		if (error)
+			return error;
+
+		sprintf(data, "%04x\n", (u16) val32);
 		for (i = 0; i <= strlen(data); i++) {
 			if (i % 2 == 0) {
 				tmp[j] = ' ';
Signature · 1 line
2.32.0
#33 lore raw

RFC PATCH v2 5/6 staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  61 +++++++--
 drivers/staging/r8188eu/core/rtw_efuse.c      |  14 ++-
 drivers/staging/r8188eu/core/rtw_io.c         |   9 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  18 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |   4 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |   2 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |   4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   |  63 ++++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  14 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 119 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  19 ++-
 .../staging/r8188eu/include/odm_interface.h   |   2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |   6 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  |  90 ++++++++-----
 18 files changed, 354 insertions(+), 105 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +54 -7
index a41675e101ac..c76feb44ecfa 100644
@@ -99,7 +99,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
-		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+		error = rtw_read32(padapter, proc_get_read_addr, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n",
+				proc_get_read_addr, tmp);
 		break;
 	default:
 		len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
@@ -315,13 +320,20 @@ int proc_get_mac_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x0; i < 0x300; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -338,13 +350,20 @@ int proc_get_mac_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 	memset(page, 0, count);
 	for (i = 0x300; i < 0x600; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -361,13 +380,20 @@ int proc_get_mac_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x600; i < 0x800; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return error;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -384,12 +410,19 @@ int proc_get_bb_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0x800; i < 0xB00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -405,12 +438,19 @@ int proc_get_bb_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xB00; i < 0xE00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -426,12 +466,19 @@ int proc_get_bb_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xE00; i < 0x1000; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
drivers/staging/r8188eu/core/rtw_efuse.c +11 -3
index b471f6446f78..dfe60bc6a547 100644
@@ -183,9 +183,15 @@ ReadEFuseByte(
 
 	/* Check bit 32 read-ready */
 	retry = 0;
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+	if (error)
+		return;
+
 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
-		value32 = rtw_read32(Adapter, EFUSE_CTRL);
+		error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+		if (error)
+			return;
+
 		retry++;
 	}
 
@@ -194,7 +200,9 @@ ReadEFuseByte(
 	/*  Designer says that there shall be some delay after ready bit is set, or the */
 	/*  result will always stay on last data we read. */
 	udelay(50);
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+	if (error)
+		return;
 
 	*pbuf = (u8)(value32 & 0xff);
 }
drivers/staging/r8188eu/core/rtw_io.c +3 -6
index fd64893c778d..df4d8ac8aadc 100644
@@ -56,18 +56,15 @@ int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 	return _read16(pintfhdl, addr, data);
 }
 
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read32(struct adapter *adapter, u32 addr, u32 *data)
 {
-	u32 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	int	(*_read32)(struct intf_hdl *pintfhdl, u32 addr, u32 *data);
 
 	_read32 = pintfhdl->io_ops._read32;
 
-	r_val = _read32(pintfhdl, addr);
-
-	return r_val;
+	return _read32(pintfhdl, addr, data);
 }
 
 int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
drivers/staging/r8188eu/core/rtw_mp.c +15 -3
index 76f0bc399819..e990e81966af 100644
@@ -765,12 +765,17 @@ static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
 {
 	/* selection */
 	u32 phyrx_set = 0, count = 0;
+	int error;
 
 	phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
 	rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
 
 	/* Read packet count */
-	count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
+	error = rtw_read32(pAdapter, REG_RXERR_RPT, &count);
+	if (error)
+		return count;
+
+	count &= RXERR_COUNTER_MASK;
 
 	return count;
 }
@@ -803,8 +808,12 @@ u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
 static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 {
 	int psd_val;
+	int error;
+
+	error = rtw_read32(pAdapter, 0x808, &psd_val);
+	if (error)
+		return 0;
 
-	psd_val = rtw_read32(pAdapter, 0x808);
 	psd_val &= 0xFFBFFC00;
 	psd_val |= point;
 
@@ -814,7 +823,10 @@ static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 
 	rtw_write32(pAdapter, 0x808, psd_val);
 	mdelay(1);
-	psd_val = rtw_read32(pAdapter, 0x8B4);
+
+	error = rtw_read32(pAdapter, 0x8B4, &psd_val);
+	if (error)
+		return 0;
 
 	psd_val &= 0x0000FFFF;
 
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +3 -1
index c6f7636c2174..9eaef9c73516 100644
@@ -659,7 +659,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 		break;
 	default:
 		width = 4;
-		RegRWStruct->value = rtw_read32(Adapter, offset);
+		error = rtw_read32(Adapter, offset, &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	}
 
drivers/staging/r8188eu/core/rtw_pwrctrl.c +4 -1
index c3897b29121c..4335907acbc3 100644
@@ -55,6 +55,7 @@ int ips_leave(struct adapter *padapter)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	int result = _SUCCESS;
 	int keyid;
+	u32 tmp;
 
 	_enter_pwrlock(&pwrpriv->lock);
 
@@ -83,7 +84,9 @@ int ips_leave(struct adapter *padapter)
 			}
 		}
 
-		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
+		if (!rtw_read32(padapter, 0x4c, &tmp))
+			DBG_88E("==> ips_leave.....LED(0x%08x)...\n", tmp);
+
 		pwrpriv->bips_processing = false;
 
 		pwrpriv->bkeepfwalive = false;
drivers/staging/r8188eu/core/rtw_sreset.c +7 -2
index 8e1bc62e74e5..ec5d070e1641 100644
@@ -29,13 +29,18 @@ u8 sreset_get_wifi_status(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	u8 status = WIFI_STATUS_SUCCESS;
 	u32 val32 = 0;
 
 	if (psrtpriv->silent_reset_inprogress)
 		return status;
-	val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
+	error = rtw_read32(padapter, REG_TXDMA_STATUS, &val32);
+	if (error) {
+		psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
+		return WIFI_MAC_TXDMA_ERROR;
+	}
+
 	if (val32 == 0xeaeaeaea) {
 		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
 	} else if (val32 != 0) {
drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c +4 -4
index d873672feb27..bd4580eba0a9 100644
@@ -316,19 +316,19 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0000000d;
 		break;
 	case 12:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR0);
+		ODM_Read4Byte(dm_odm, REG_ARFR0, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 13:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR1);
+		ODM_Read4Byte(dm_odm, REG_ARFR1, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 14:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR2);
+		ODM_Read4Byte(dm_odm, REG_ARFR2, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 15:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR3);
+		ODM_Read4Byte(dm_odm, REG_ARFR3, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	default:
drivers/staging/r8188eu/hal/HalPhyRf_8188e.c +1 -1
index 3545ad60dc00..725a18dc3979 100644
@@ -667,7 +667,7 @@ static void _PHY_SaveMACRegisters(
 		if (error)
 			return;
 	}
-	MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
+	ODM_Read4Byte(dm_odm, MACReg[i], MACBackup + i);
 }
 
 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 669d3e5eafb6..a47319dec231 100644
@@ -16,10 +16,10 @@ int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data)
 	return rtw_read16(Adapter, RegAddr, data);
 }
 
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read32(Adapter, RegAddr);
+	return rtw_read32(Adapter, RegAddr, data);
 }
 
 void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +51 -12

126 lines not on this page · raw message

drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +10 -2
index 3afb66195413..24b2afb62d68 100644
@@ -75,8 +75,12 @@ rtl8188e_PHY_QueryBBReg(
 	)
 {
 	u32 ReturnValue = 0, OriginalValue, BitShift;
+	int error;
+
+	error = rtw_read32(Adapter, RegAddr, &OriginalValue);
+	if (error)
+		return ReturnValue;
 
-	OriginalValue = rtw_read32(Adapter, RegAddr);
 	BitShift = phy_CalculateBitShift(BitMask);
 	ReturnValue = (OriginalValue & BitMask) >> BitShift;
 	return ReturnValue;
@@ -103,9 +107,13 @@ rtl8188e_PHY_QueryBBReg(
 void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
 {
 	u32 OriginalValue, BitShift;
+	int error;
 
 	if (BitMask != bMaskDWord) { /* if not "double word" write */
-		OriginalValue = rtw_read32(Adapter, RegAddr);
+		error = rtw_read32(Adapter, RegAddr, &OriginalValue);
+		if (error)
+			return;
+
 		BitShift = phy_CalculateBitShift(BitMask);
 		Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
 	}
drivers/staging/r8188eu/hal/rtl8188e_sreset.c +9 -5
index 39dacfb23570..a023a0669ffd 100644
@@ -14,14 +14,16 @@ void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	unsigned long current_time;
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	unsigned int diff_time;
 	u32 txdma_status;
 
-	txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
-	if (txdma_status != 0x00) {
+	error = rtw_read32(padapter, REG_TXDMA_STATUS, &txdma_status);
+	if (error) {
+		return;
+	} else if (txdma_status != 0x00) {
 		DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
 		rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
 		rtl8188e_silentreset_for_specific_platform(padapter);
@@ -51,8 +53,10 @@ void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
 	u8 fw_status = 0;
 	int error;
 
-	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
-	if (rx_dma_status != 0x00) {
+	error = rtw_read32(padapter, REG_RXDMA_STATUS, &rx_dma_status);
+	if (error) {
+		return;
+	} else if (rx_dma_status != 0x00) {
 		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
 	}
drivers/staging/r8188eu/hal/usb_halinit.c +100 -19

252 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_ops_linux.c +15 -4
index 58e852555f54..bcb589777b51 100644
@@ -152,21 +152,32 @@ static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 	return res;
 }
 
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+	} else {
+		/* Noone cares about positive return value */
+		*data = le32_to_cpu(tmp);
+		res = 0;
+	}
 
-	return le32_to_cpu(data);
+	return res;
 }
 
 static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 2455dae6eebb..bbb1045c9e7d 100644
@@ -64,7 +64,7 @@ int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
 int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data);
 
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 *data);
 
 void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index c44554c848cf..501168457518 100644
@@ -87,7 +87,7 @@ struct io_queue;
 struct _io_ops {
 	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
-	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read32)(struct intf_hdl *pintfhdl, u32 addr, u32 *data);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
 	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
@@ -250,7 +250,7 @@ void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
 int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
 int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data);
-u32 _rtw_read32(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read32(struct adapter *adapter, u32 addr, u32 *data);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port_cancel(struct adapter *adapter);
@@ -272,7 +272,7 @@ void _rtw_write_port_cancel(struct adapter *adapter);
 
 #define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
 #define rtw_read16(adapter, addr, data) _rtw_read16((adapter), (addr), (data))
-#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
+#define rtw_read32(adapter, addr, data) _rtw_read32((adapter), (addr), (data))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
 	_rtw_read_mem((adapter), (addr), (cnt), (mem))
 #define rtw_read_port(adapter, addr, cnt, mem)				\
drivers/staging/r8188eu/os_dep/ioctl_linux.c +61 -29

195 lines not on this page · raw message

Signature · 1 line
2.32.0
#105 lore raw

RFC PATCH v2 6/6 staging: r8188eu: make ReadEFuse return an int

In reply to Pavel Skripkin

ReadEFuse can fail in case of _rtw_read() failure. Callers should handle this error to avoid uninit value bugs, since ReadEFuse won't initialized passed pbuf in case of usb transfer failure.

To achieve it, ReadEFuseByte() now returns an int and all callers of ReadEFuseByte() passes error code up to calltrace to rtw_usb_if1_init(), which fails when reading regiters fails.

---
 drivers/staging/r8188eu/core/rtw_efuse.c      | 45 ++++++++-----
 drivers/staging/r8188eu/hal/hal_intf.c        |  6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 65 ++++++++++++-------
 drivers/staging/r8188eu/hal/usb_halinit.c     | 18 +++--
 drivers/staging/r8188eu/include/hal_intf.h    |  6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |  2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |  4 +-
 drivers/staging/r8188eu/os_dep/usb_intf.c     |  3 +-
 8 files changed, 96 insertions(+), 53 deletions(-)
drivers/staging/r8188eu/core/rtw_efuse.c +30 -15
index dfe60bc6a547..5bfcf80b2678 100644
@@ -149,7 +149,7 @@ Efuse_CalculateWordCnts(u8 word_en)
 /*  */
 /* 	Created by Roger, 2008.10.21. */
 /*  */
-void
+int
 ReadEFuseByte(
 		struct adapter *Adapter,
 		u16 _offset,
@@ -163,21 +163,21 @@ ReadEFuseByte(
 
 	if (pseudo) {
 		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
-		return;
+		return 0;
 	}
 
 	/* Write Address */
 	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
 	error = rtw_read8(Adapter, EFUSE_CTRL + 2, &readbyte);
 	if (error)
-		return;
+		return error;
 
 	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 
 	/* Write bit 32 0 */
 	error = rtw_read8(Adapter, EFUSE_CTRL + 3, &readbyte);
 	if (error)
-		return;
+		return error;
 
 	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
 
@@ -185,12 +185,12 @@ ReadEFuseByte(
 	retry = 0;
 	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 	if (error)
-		return;
+		return error;
 
 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
 		error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 		if (error)
-			return;
+			return error;
 
 		retry++;
 	}
@@ -202,9 +202,11 @@ ReadEFuseByte(
 	udelay(50);
 	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 	if (error)
-		return;
+		return error;
 
 	*pbuf = (u8)(value32 & 0xff);
+
+	return 0;
 }
 
 /*  */
@@ -225,9 +227,9 @@ ReadEFuseByte(
 /* 					write addr must be after sec5. */
 /*  */
 
-static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
+static int efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
 {
-	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
+	return Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
 }
 
 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
@@ -538,6 +540,7 @@ u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int error;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -546,7 +549,9 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	error = efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	if (error)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -556,6 +561,7 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int error;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -564,7 +570,9 @@ u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	error = efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	if (error)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -835,17 +843,22 @@ efuse_ShadowRead4Byte(
  * 11/11/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+static int Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
 {
 	u16 mapLen = 0;
+	int error;
 
 	Efuse_PowerSwitch(pAdapter, false, true);
 
 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 
-	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	error = efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	if (error)
+		return error;
 
 	Efuse_PowerSwitch(pAdapter, false, false);
+
+	return 0;
 }
 
 /*-----------------------------------------------------------------------------
@@ -864,7 +877,7 @@ static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse,
  * 11/13/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-void EFUSE_ShadowMapUpdate(
+int EFUSE_ShadowMapUpdate(
 	struct adapter *pAdapter,
 	u8 efuseType,
 	bool pseudo)
@@ -877,7 +890,9 @@ void EFUSE_ShadowMapUpdate(
 	if (pEEPROM->bautoload_fail_flag)
 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 	else
-		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+		return Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+
+	return 0;
 } /*  EFUSE_ShadowMapUpdate */
 
 /*-----------------------------------------------------------------------------
drivers/staging/r8188eu/hal/hal_intf.c +4 -2
index a6d589e89aeb..dce9a58eaf6f 100644
@@ -12,10 +12,12 @@ void rtw_hal_chip_configure(struct adapter *adapt)
 		adapt->HalFunc.intf_chip_configure(adapt);
 }
 
-void rtw_hal_read_chip_info(struct adapter *adapt)
+int rtw_hal_read_chip_info(struct adapter *adapt)
 {
 	if (adapt->HalFunc.read_adapter_info)
-		adapt->HalFunc.read_adapter_info(adapt);
+		return adapt->HalFunc.read_adapter_info(adapt);
+
+	return _FAIL;
 }
 
 void rtw_hal_read_chip_version(struct adapter *adapt)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +42 -23

173 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_halinit.c +12 -6
index 3826476e3396..687baf4d9d97 100644
@@ -1296,7 +1296,7 @@ readAdapterInfo_8188EU(
 	_ReadLEDSetting(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
 }
 
-static void _ReadPROMContent(
+static int _ReadPROMContent(
 	struct adapter *Adapter
 	)
 {
@@ -1307,7 +1307,7 @@ static void _ReadPROMContent(
 	/* check system boot selection */
 	error = rtw_read8(Adapter, REG_9346CR, &eeValue);
 	if (error)
-		return;
+		return error;
 
 	eeprom->EepromOrEfuse		= (eeValue & BOOT_FROM_EEPROM) ? true : false;
 	eeprom->bautoload_fail_flag	= (eeValue & EEPROM_EN) ? false : true;
@@ -1315,8 +1315,13 @@ static void _ReadPROMContent(
 	DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"),
 		(eeprom->bautoload_fail_flag ? "Fail" : "OK"));
 
-	Hal_InitPGData88E(Adapter);
+	error = Hal_InitPGData88E(Adapter);
+	if (error)
+		return error;
+
 	readAdapterInfo_8188EU(Adapter);
+
+	return 0;
 }
 
 static void _ReadRFType(struct adapter *Adapter)
@@ -1333,19 +1338,20 @@ static int _ReadAdapterInfo8188EU(struct adapter *Adapter)
 	MSG_88E("====> %s\n", __func__);
 
 	_ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
-	_ReadPROMContent(Adapter);
+	if (_ReadPROMContent(Adapter))
+		return _FAIL;
 
 	MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
 
 	return _SUCCESS;
 }
 
-static void ReadAdapterInfo8188EU(struct adapter *Adapter)
+static int ReadAdapterInfo8188EU(struct adapter *Adapter)
 {
 	/*  Read EEPROM size before call any EEPROM function */
 	Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter);
 
-	_ReadAdapterInfo8188EU(Adapter);
+	return _ReadAdapterInfo8188EU(Adapter);
 }
 
 #define GPIO_DEBUG_PORT_NUM 0
drivers/staging/r8188eu/include/hal_intf.h +3 -3
index fa252540e596..9241af39e3a3 100644
@@ -154,7 +154,7 @@ struct hal_ops {
 
 	void	(*intf_chip_configure)(struct adapter *padapter);
 
-	void	(*read_adapter_info)(struct adapter *padapter);
+	int	(*read_adapter_info)(struct adapter *padapter);
 
 	void	(*enable_interrupt)(struct adapter *padapter);
 	void	(*disable_interrupt)(struct adapter *padapter);
@@ -222,7 +222,7 @@ struct hal_ops {
 
 	void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite,
 				 u8 PwrState);
-	void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
+	int (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
 			  u16 _size_byte, u8 *pbuf, bool bPseudoTest);
 	void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType,
 					u8 type, void *pOut, bool bPseudoTest);
@@ -324,7 +324,7 @@ void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 
 void rtw_hal_chip_configure(struct adapter *padapter);
-void rtw_hal_read_chip_info(struct adapter *padapter);
+int rtw_hal_read_chip_info(struct adapter *padapter);
 void rtw_hal_read_chip_version(struct adapter *padapter);
 
 u8 rtw_hal_set_def_var(struct adapter *padapter,
drivers/staging/r8188eu/include/rtl8188e_hal.h +1 -1
index 3939bf053de1..db9adbd0b024 100644
@@ -410,7 +410,7 @@ s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy);
 
 /*  EFuse */
 u8 GetEEPROMSize8188E(struct adapter *padapter);
-void Hal_InitPGData88E(struct adapter *padapter);
+int Hal_InitPGData88E(struct adapter *padapter);
 void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo);
 void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo,
 			    bool AutoLoadFail);
drivers/staging/r8188eu/include/rtw_efuse.h +2 -2
index b3ff46db2091..9657b66679e3 100644
@@ -113,7 +113,7 @@ u8 rtw_BT_efuse_map_write(struct adapter *adapter, u16 addr,
 			  u16 cnts, u8 *data);
 u16 Efuse_GetCurrentSize(struct adapter *adapter, u8 efusetype, bool test);
 u8 Efuse_CalculateWordCnts(u8 word_en);
-void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
+int ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
 void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1,
 			      void *out, bool bPseudoTest);
 u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data, bool test);
@@ -128,7 +128,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
 			     u8 word_en, u8 *data, bool test);
 
 u8 EFUSE_Read1Byte(struct adapter *adapter, u16 address);
-void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
+int EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
 void EFUSE_ShadowRead(struct adapter *adapt, u8 type, u16 offset, u32 *val);
 
 #endif
drivers/staging/r8188eu/os_dep/usb_intf.c +2 -1
index e002070f7fba..7a1a296f66b5 100644
@@ -608,7 +608,8 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
 	rtw_hal_chip_configure(padapter);
 
 	/* step read efuse/eeprom data and get mac_addr */
-	rtw_hal_read_chip_info(padapter);
+	if (rtw_hal_read_chip_info(padapter) == _FAIL)
+		goto free_hal_data;
 
 	/* step 5. */
 	if (rtw_init_drv_sw(padapter) == _FAIL)
Signature · 1 line
2.32.0
#119 lore raw
In reply to Fabio M. De Francesco
Quoted 36 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 10 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

Quoted 1 line
Quoted 1 line
Quoted 1 line

In summation. if anything should be changed, it is the code of the

callers of

Quoted 1 line
Quoted 1 line
Quoted 1 line

_rtw_read*() if you find out they they don't properly handle the

returning

Quoted 1 line
Quoted 1 line
Quoted 1 line

values of this function. You should find every place where _rtw_read*()

are

Quoted 1 line
Quoted 1 line
Quoted 1 line

called and figure out if the returns are properly checked and handled;

if not,

Quoted 6 lines
Quoted 3 lines
Quoted 3 lines

make some change only there.

Larry, Philip, where are you? Am I missing something?

Relax, there is no need to get jumpy, people do not have to respond instantly to emails here. Especially when it is not their job to do so.

Quoted 13 lines

I should have placed a big smile at the end of the phrase. I was just kidding while trying to get their attention. I know there is no hurry and that no one has any obligation of this kind. Again, just kidding :)

Thanks,

Fabio

Quoted 1 line

greg k-h

Dear Fabio,

I can't speak for anyone else, but I will reply to as many e-mails as I'm able - there is no need to try and get my attention, you shall have it by default, as and when I am able to give it :-)

As V2 has been sent out by Pavel, I will try and take a look soon.

Regards,
Phil

#106 lore raw
In reply to Pavel Skripkin
Quoted 34 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Quoted 2 lines

Only build-tested, since I don't have device with r8118eu chip

BTW, can you recommend any devices with this chip except for ASUS USB-N10 Nano? I didn't find any of them with delivery/reasonable delivery price to Russia.

I want to help with testing and moving this driver out of staging directory :)

With regards,
Pavel Skripkin

#117 lore raw
In reply to Pavel Skripkin
Quoted 24 lines · CEST Pavel Skripkin
Quoted 12 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

Quoted 8 lines
Quoted 3 lines

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

That's what I've done in v2. All rtw_read* family will have following prototype in v2:

Quoted 6 lines

int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);

Was it your idea, or you were talking about different approach?

With regards,
Pavel Skripkin

Pavel,

Yes, it is correct.

However, after that I had time to look at the calls chain and understand what each function does and then I saw that my initial proposal should be made along with another one...

The calls chain is:

(1) _rtw_read8() <--- (returns the data read from next function in chain)
(no errors returned, see possible fix in next function)
(2) usb_read8() <--- (returns the data read from next function in chain)
(_data_may_be_unitialised_, no errors returned)
(possible fix: from "u8 data"; to "char data = -1;")
(3) usbctrl_vendorreq() <---- (returns data read from next function in chain)
(data is always a valid pointer saved to third argument) (if it fails, the third argument is unchanged because it still has the address of the "data" argument given by the caller)
(4) usb_control_msg() <---- (it always returns how many bytes read or valid error codes)
(it _never_ returns 0: either positive or negative values)

I have not yet looked at the usb_control_msg_recv() which Greg talked about.

To summarize: in function (2) "u8 data" should become "char data = -1;".

Regards,

Fabio

P.S.: I was about to send this message while I see that you sent v2. Since I've already have this response to your question I send it and soon after I'm going to read your v2 patches.

#107 lore raw
In reply to Pavel Skripkin
Quoted 3 lines · Pavel Skripkin

BTW, can you recommend any devices with this chip except for ASUS USB-N10 Nano? I didn't find any of them with delivery/reasonable delivery price to Russia.

I want to help with testing and moving this driver out of staging directory :)

Hi Pavel,

My one is a TP-LINK WN725N (not sure, but I guess v2). You could also have a look at the device table in os_dep/usb_intf.c

Regards,
Michael

#118 lore raw
In reply to Fabio M. De Francesco
Quoted 18 lines · Fabio M. De Francesco
Quoted 17 lines · CEST Pavel Skripkin
Quoted 16 lines · Fabio M. De Francesco
Quoted 3 lines · CEST Greg KH
Quoted 2 lines · Pavel Skripkin
Quoted 1 line · Fabio M. De Francesco

On Sunday, August 22, 2021 12:09:29 PM CEST Pavel Skripkin wrote:

[...]

Quoted 10 lines
Quoted 6 lines
Quoted 2 lines

So, it's up to the callers to test if (!_rtw_read*()) and then act accordingly. If they get 0 they should know how to handle the errors.

Yes, but _rtw_read*() == 0 indicates 2 states:
1. Error on transfer side
2. Actual register value is 0

That's not a good design, it should be fixed. Note there is the new usb_control_msg_recv() function which should probably be used instead here, to prevent this problem from happening.

Quoted 8 lines
Quoted 8 lines
Quoted 4 lines

I think that no functions should return 0 for signaling FAILURE. If I'm not wrong, the kernel quite always prefers to return 0 on SUCCESS and <0 on FAILURE. Why don't you just fix this?

That's what I've done in v2. All rtw_read* family will have following prototype in v2:

int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);

(*)

Quoted 13 lines
Quoted 4 lines

Was it your idea, or you were talking about different approach?

With regards,
Pavel Skripkin

Pavel,

Yes, it is correct.

However, after that I had time to look at the calls chain and understand what each function does and then I saw that my initial proposal should be made along with another one...

Quoted 7 lines

The calls chain is:

(1) _rtw_read8() <--- (returns the data read from next function in chain)
(no errors returned, see possible fix in next function)
(2) usb_read8() <--- (returns the data read from next function in chain)
(_data_may_be_unitialised_, no errors returned)
(possible fix: from "u8 data"; to "char data = -1;")

Anyway char will be cast to u8 and -1 will become 0xff. 0xff is still valid register value, I guess.

Quoted 4 lines

(3) usbctrl_vendorreq() <---- (returns data read from next function in chain)
(data is always a valid pointer saved to third argument) (if it fails, the third argument is unchanged because it
still has the address of the "data" argument given by the caller) > (4) usb_control_msg() <---- (it always returns how

many bytes read or valid error codes)

Quoted 6 lines

(it _never_ returns 0: either positive or negative values)

I have not yet looked at the usb_control_msg_recv() which Greg talked about.

To summarize: in function (2) "u8 data" should become "char data = -1;".

So, anyway caller _should_ somehow receive an error from usb_control_msg(). We can just change rtw_read{8,16,32} return values from u{8,16,32} to int32, but anyway it will require all changes, that I've done in this series, but in slightly different form. I.e temp int32 variable + error checking + casting int to u{8,16,32}.

Doesn't it make sense to just switch to more standard prototype (*)? All other drivers use this prototype for their private reading functions.

With regards,
Pavel Skripkin

#108 lore raw
In reply to Michael Straube
Quoted 3 lines · Michael Straube

Hi Pavel,

My one is a TP-LINK WN725N (not sure, but I guess v2).

Wow! I found this one in my city, thank you!

Quoted 2 lines

You could also have a look at the device table in os_dep/usb_intf.c

Yep, but I wanted to hear from driver reviewers/maintainers about what they use to test. I guess, some devices could be broken or not unwieldy to use. Thank you for recommendation, will buy one in few days :)

With regards,
Pavel Skripkin

#31 lore raw

Re: [PATCH RFC v2 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin
reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross #…

Hi Pavel,

[FYI, it's a private test report for your RFC patch.] [auto build test WARNING on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210822-233538
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: arc-allyesconfig (attached as .config)
compiler: arceb-elf-gcc (GCC) 11.2.0

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/2b557bc2dab8449fa9bb37a8a4c36b0714b007f7
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210822-233538 git checkout 2b557bc2dab8449fa9bb37a8a4c36b0714b007f7
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arc

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

drivers/staging/r8188eu/os_dep/ioctl_linux.c: In function 'rtw_dbg_mode_hdl':

>> drivers/staging/r8188eu/os_dep/ioctl_linux.c:2258:13: warning: variable 'error' set but not used [-Wunused-but-set-variable]
    2258 |         int error;
         |             ^~~~~

vim +/error +2258 drivers/staging/r8188eu/os_dep/ioctl_linux.c

2250
2251 static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 len)
2252 {
2253 struct mp_rw_reg *RegRWStruct;
2254 struct rf_reg_param *prfreg;
2255 u8 path;
2256 u8 offset;
2257 u32 value;

> 2258		int error;

2259
2260 DBG_88E("%s\n", __func__);
2261
2262 switch (id) {
2263 case GEN_MP_IOCTL_SUBCODE(MP_START):
2264 DBG_88E("871x_driver is only for normal mode, can't enter mp mode\n");
2265 break;
2266 case GEN_MP_IOCTL_SUBCODE(READ_REG):
2267 RegRWStruct = (struct mp_rw_reg *)pdata;
2268 switch (RegRWStruct->width) {
2269 case 1:
2270 error = rtw_read8(padapter, RegRWStruct->offset,
2271 (u8 *) &RegRWStruct->value);
2272 break;
2273 case 2:
2274 RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
2275 break;
2276 case 4:
2277 RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
2278 break;
2279 default:
2280 break;
2281 }
2282
2283 break;
2284 case GEN_MP_IOCTL_SUBCODE(WRITE_REG):
2285 RegRWStruct = (struct mp_rw_reg *)pdata;
2286 switch (RegRWStruct->width) {
2287 case 1:
2288 rtw_write8(padapter, RegRWStruct->offset, (u8)RegRWStruct->value);
2289 break;
2290 case 2:
2291 rtw_write16(padapter, RegRWStruct->offset, (u16)RegRWStruct->value);
2292 break;
2293 case 4:
2294 rtw_write32(padapter, RegRWStruct->offset, (u32)RegRWStruct->value);
2295 break;
2296 default:
2297 break;
2298 }
2299
2300 break;
2301 case GEN_MP_IOCTL_SUBCODE(READ_RF_REG):
2302
2303 prfreg = (struct rf_reg_param *)pdata;
2304
2305 path = (u8)prfreg->path;
2306 offset = (u8)prfreg->offset;
2307
2308 value = rtw_hal_read_rfreg(padapter, path, offset, 0xffffffff);
2309
2310 prfreg->value = value;
2311
2312 break;
2313 case GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG):
2314
2315 prfreg = (struct rf_reg_param *)pdata;
2316
2317 path = (u8)prfreg->path;
2318 offset = (u8)prfreg->offset;
2319 value = prfreg->value;
2320
2321 rtw_hal_write_rfreg(padapter, path, offset, 0xffffffff, value);
2322
2323 break;
2324 case GEN_MP_IOCTL_SUBCODE(TRIGGER_GPIO):
2325 DBG_88E("==> trigger gpio 0\n");
2326 rtw_hal_set_hwreg(padapter, HW_VAR_TRIGGER_GPIO_0, NULL);
2327 break;
2328 case GEN_MP_IOCTL_SUBCODE(GET_WIFI_STATUS):
2329 *pdata = rtw_hal_sreset_get_wifi_status(padapter);
2330 break;
2331 default:
2332 break;
2333 }
2334 }
2335

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#110 lore raw
In reply to Pavel Skripkin
Quoted 35 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, I've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Quoted 7 lines

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

Hi Pavel,

I've just read your v2 of the series. I had no time to read each and every line, however, I suppose that I saw enough to say that I think they are a huge improvement over v1. I really like your patches and if I were you, I'd drop that RFC tag.

Thanks,

Fabio
v1 design.
not needed because

#111 lore raw
Quoted 44 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, I've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Quoted 7 lines

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

Quoted 7 lines

Hi Pavel,

I've just read your v2 of the series. I had no time to read each and every line, however, I suppose that I saw enough to say that I think they are a huge improvement over v1. I really like your patches and if I were you, I'd drop that RFC tag.

Thank you, Fabio! I appreciate it :)

With regards,
Pavel Skripkin

#112 lore raw
Quoted 53 lines · CEST Pavel Skripkin
Quoted 44 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, I've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Quoted 7 lines

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

Quoted 7 lines

Hi Pavel,

I've just read your v2 of the series. I had no time to read each and every line, however, I suppose that I saw enough to say that I think they are a huge improvement over v1. I really like your patches and if I were you, I'd drop that RFC tag.

Quoted 5 lines

Thank you, Fabio! I appreciate it :)

With regards,
Pavel Skripkin

Hi Pavel,

I've read more code of your series and I'm ready to give a formal ack. However, I'm not sure about the rules: can it be also given to RFC or only to "real" patches?

As I've already said, they look good and I like them. So, the entire series is...

If the rules don't allow to formally ack RFC, I will be happy to ack again the final product.

I also want to say that I enjoyed discussing this work with you on this long thread. :-)

Thanks,

Fabio

#113 lore raw
Quoted 60 lines · Fabio M. De Francesco
Quoted 53 lines · CEST Pavel Skripkin
Quoted 44 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, I've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Quoted 7 lines

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

Quoted 7 lines

Hi Pavel,

I've just read your v2 of the series. I had no time to read each and every line, however, I suppose that I saw enough to say that I think they are a huge improvement over v1. I really like your patches and if I were you, I'd drop that RFC tag.

Quoted 5 lines

Thank you, Fabio! I appreciate it :)

With regards,
Pavel Skripkin

Quoted 7 lines

Hi Pavel,

I've read more code of your series and I'm ready to give a formal ack. However, I'm not sure about the rules: can it be also given to RFC or only to "real" patches?

As I've already said, they look good and I like them. So, the entire series is...

AFAIK, RFC patches can be treated as normal patches, if reviewers/maintainers don't have objections to code. I am not sure about it, since it's my first experience with RFCs :)

Anyway, thank you for ACKing. Let's see what Larry thinks about it. I believe, he can find some bugs in my code since it's not tested at all :) I hope, my r8118eu device will come soon and I will be able to test this series...

Quoted 6 lines

If the rules don't allow to formally ack RFC, I will be happy to ack again the final product.

I also want to say that I enjoyed discussing this work with you on this long thread. :-)

Me too, thank you. Technical discussions are the best part of linux kernel development process, IMO :)

With regards,
Pavel Skripkin

#109 lore raw
In reply to Pavel Skripkin
Quoted 12 lines · Pavel Skripkin
Quoted 3 lines · Michael Straube

Hi Pavel,

My one is a TP-LINK WN725N (not sure, but I guess v2).

Wow! I found this one in my city, thank you!

Quoted 2 lines

You could also have a look at the device table in os_dep/usb_intf.c

Quoted 8 lines

Yep, but I wanted to hear from driver reviewers/maintainers about what they use to test. I guess, some devices could be broken or not unwieldy to use. Thank you for recommendation, will buy one in few days :)

With regards,
Pavel Skripkin

Dear Pavel,

Glad you found one :-) Mine is the N10-Nano as that was all I could find at the time.

Regards,
Phil

#114 lore raw
In reply to Pavel Skripkin
Quoted 77 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  57 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1138 insertions(+), 389 deletions(-)
Quoted 3 lines

--
2.32.0

Dear Pavel,

Thanks for this. I like the code a lot. One thing I am conflicted on is the helper macro for the printing of register values though. Whilst I'm not necessarily opposed to the concept of the macro itself, I don't think it should rely on GlobalDebugLevel for one thing - if we are going to control printing of messages at runtime then in my mind this should be done via debugfs and pr_debug or similar - an in-kernel mechanism rather than something driver-provided. Also, the example you give of:

        u32 tmp;
        if (!rtw_read(&tmp))
                DBG("reg = %d\n", tmp);

Doesn't seem overly unclear to me if DBG was a pr_debug or similar, but I get what you're saying about repetition. This is just a small thing though, would be interested to see what others think. Many thanks.

Regards,
Phil

#115 lore raw
Quoted 84 lines · Phillip Potter
Quoted 77 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  57 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1138 insertions(+), 389 deletions(-)
Quoted 3 lines

--
2.32.0

Dear Pavel,

Quoted 7 lines

Thanks for this. I like the code a lot. One thing I am conflicted on is the helper macro for the printing of register values though. Whilst I'm not necessarily opposed to the concept of the macro itself, I don't think it should rely on GlobalDebugLevel for one thing - if we are going to control printing of messages at runtime then in my mind this should be done via debugfs and pr_debug or similar - an in-kernel mechanism rather than something driver-provided. Also, the example you

I've copy-pasted previous DBG() macro. I have a plan to clean up these debug macros in future, but I want to make these clean ups on top of this RFC to not rebase this huge patch set many times :)

Quoted 11 lines

give of:

         u32 tmp;
         if (!rtw_read(&tmp))
                 DBG("reg = %d\n", tmp);

Doesn't seem overly unclear to me if DBG was a pr_debug or similar, but I get what you're saying about repetition. This is just a small thing though, would be interested to see what others think. Many thanks.

To be honest, I made this macro, because I am lazy :P rtw_dbg_port() had a lot DBG_88E() calls with just register value, so I decided to wrap this.

I still believe, that this macro is useful, since callers won't care about creating temp variable and checking read() error code. This macro doesn't cover situation, where we want to print register + smth else, so if you have any idea about improvements, please, let me know :)

With regards,
Pavel Skripkin

#116 lore raw
In reply to Phillip Potter
Quoted 93 lines · Phillip Potter
Quoted 77 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

Why is this pacth series RFC?
1. I don't have this device and I cannot test these changes.
2. I don't know how to handle errors in each particular case. For now, function just returns or returns an error. That's all. I hope, driver maintainers will help with these bits.
3. I guess, I handled not all uninit value bugs here. I hope, I fixed at least half of them

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Only build-tested, since I don't have device with r8118eu chip

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  57 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1138 insertions(+), 389 deletions(-)
Quoted 3 lines

--
2.32.0

Dear Pavel,

Thanks for this. I like the code a lot. One thing I am conflicted on is the helper macro for the printing of register values though. Whilst I'm not necessarily opposed to the concept of the macro itself, I don't think it should rely on GlobalDebugLevel for one thing - if we are going to control printing of messages at runtime then in my mind this should be done via debugfs and pr_debug or similar - an in-kernel mechanism rather than something driver-provided. Also, the example you give of:

Quoted 9 lines
         u32 tmp;
         if (!rtw_read(&tmp))
                 DBG("reg = %d\n", tmp);

Doesn't seem overly unclear to me if DBG was a pr_debug or similar, but I get what you're saying about repetition. This is just a small thing though, would be interested to see what others think. Many thanks.

Btw, did you have a chance to test these changes? My r8188eu device _should_ come in few days, so I am not able to test it right now :)

With regards,
Pavel Skripkin

#34 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Regards,
Phil

#35 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Regards,

Fabio

Quoted 4 lines

Regards,
Phil

#36 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

If I am missing something, please, let me know :) v3 is on the way...

With regards,
Pavel Skripkin

#43 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Phillip Potter
Quoted 46 lines · Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Quoted 11 lines

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

The most strange thing is why gcc didn't complain about different pointer types... I think, that gcc must complain about this type of not explicit casts, because 99% it's a bug.

Again big thanks for analysis :)

With regards,
Pavel Skripkin

#102 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 12 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 173

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +3 -1
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);

Add a return here. Try to keep the success path and the failure path as separate as possible. Try to keep the success path indented at one tab so the code looks like this:

	success();
	success();
	if (fail)
		handle_failure();
	success();
	success();

Try to deal with exceptions as quickly as possible so that the reader has less to remember.

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 175

Quoted 2 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +2 -0
+	} else {
+		/* Noone cares about positive return value */

Ugh... That's unfortunate. We should actually care. The usbctrl_vendorreq() has an information leak where it copies len (4) bytes of data even if usb_control_msg() is not able to read len bytes.

The best fix would be to remove the information leak and make usbctrl_vendorreq() return zero on success. In other words something like:

	status = usb_control_msg();
	if (status < 0)
		return status;
	if (status != len)
		return -EIO;
	status = 0;
Quoted 7 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +4 -1
+		*data = le32_to_cpu(tmp);
+		res = 0;
+	}
 
-	return le32_to_cpu(data);
+	return res;
 }
#103 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 49 lines · Dan Carpenter
Quoted 12 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 173

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +3 -1
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);

Add a return here. Try to keep the success path and the failure path as separate as possible. Try to keep the success path indented at one tab so the code looks like this:

	success();
	success();
	if (fail)
		handle_failure();
	success();
	success();

Try to deal with exceptions as quickly as possible so that the reader has less to remember.

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 175

Quoted 2 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +2 -0
+	} else {
+		/* Noone cares about positive return value */

Ugh... That's unfortunate. We should actually care. The usbctrl_vendorreq() has an information leak where it copies len (4) bytes of data even if usb_control_msg() is not able to read len bytes.

The best fix would be to remove the information leak and make usbctrl_vendorreq() return zero on success. In other words something like:

Quoted 7 lines
	status = usb_control_msg();
	if (status < 0)
		return status;
	if (status != len)
		return -EIO;
	status = 0;

I see, thank you for reviewing, will fix in v3! I fully forgot, that usb_control_msg() can receive only part of the message :)

With regards,
Pavel Skripkin

#44 lore raw

v3 cover staging: r8188eu: avoid uninit value bugs

In reply to Phillip Potter

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

v2 -> v3:
1. Fixed OOPS in usb_read32(), caused by writing to u32 **
2. Fixed style in rtw_read32, rtw_read16 and rtw_read8 (Suggested by Dan)
3. Added error hanling when usb_control_msg() returns ret != len
NOTE: Dan suggested to add this to usbctrl_vendorreq(), but there is pending series, which will get rid of usb_control_msg(), so (res != len) check can be removed, when Fabio's series will go in
4. Removed RFC tag

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Phillip has tested fixed v2 version, AFAIU

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  62 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1143 insertions(+), 389 deletions(-)
Signature · 1 line
2.32.0
#45 lore raw

PATCH v3 1/6 staging: r8188eu: remove {read,write}_macreg

These 2 functions are unused, so they can be simply removed

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 39 ------------------------
 drivers/staging/r8188eu/include/rtw_mp.h |  2 --
 2 files changed, 41 deletions(-)
drivers/staging/r8188eu/core/rtw_mp.c +0 -39
index 93bb683b628f..0a0a24fd37b0 100644
@@ -7,45 +7,6 @@
 #include "../include/odm_precomp.h"
 #include "../include/rtl8188e_hal.h"
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz)
-{
-	u32 val = 0;
-
-	switch (sz) {
-	case 1:
-		val = rtw_read8(padapter, addr);
-		break;
-	case 2:
-		val = rtw_read16(padapter, addr);
-		break;
-	case 4:
-		val = rtw_read32(padapter, addr);
-		break;
-	default:
-		val = 0xffffffff;
-		break;
-	}
-
-	return val;
-}
-
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz)
-{
-	switch (sz) {
-	case 1:
-		rtw_write8(padapter, addr, (u8)val);
-		break;
-	case 2:
-		rtw_write16(padapter, addr, (u16)val);
-		break;
-	case 4:
-		rtw_write32(padapter, addr, val);
-		break;
-	default:
-		break;
-	}
-}
-
 u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask)
 {
 	return rtw_hal_read_bbreg(padapter, addr, bitmask);
drivers/staging/r8188eu/include/rtw_mp.h +0 -2
index b64b16554343..3a259d991348 100644
@@ -410,8 +410,6 @@ void mp_stop_test(struct adapter *padapter);
 u32 _read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask);
 void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val);
 
-u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
-void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
 u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
 void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
 u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
Signature · 1 line
2.32.0
#48 lore raw

PATCH v3 2/6 staging: r8188eu: add helper macro for printing registers

In reply to Pavel Skripkin

There are a lof of places, where DBG_88E() is used to print register value. Since following patches change _rtw_read*() family prototypes, we can wrap printing registers into useful macro to avoid open-coding error checking like this:

	u32 tmp;
	if (!rtw_read(&tmp))
		DBG("reg = %d\n", tmp);

So, added DBG_88E_REG{8,16,32} macros for printing register values.

---
 drivers/staging/r8188eu/include/rtw_debug.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
drivers/staging/r8188eu/include/rtw_debug.h +13 -0
index 3c3bf2a4f30e..059647b9cd3a 100644
@@ -72,6 +72,19 @@ extern u32 GlobalDebugLevel;
 			pr_info(DRIVER_PREFIX __VA_ARGS__);			\
 	} while (0)
 
+#define __DBG_88E_REG(fmt, adap, reg, size)				\
+	do {								\
+		u##size __tmp__;					\
+		if (rtw_read##size((adap), (reg), &__tmp__))		\
+			break;						\
+		if (_drv_err_ <= GlobalDebugLevel)			\
+			pr_info(DRIVER_PREFIX fmt, __tmp__);		\
+	} while (0)
+
+#define DBG_88E_REG8(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 8)
+#define DBG_88E_REG16(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 16)
+#define DBG_88E_REG32(fmt, adap, reg)	__DBG_88E_REG(fmt, adap, reg, 32)
+
 int proc_get_drv_version(char *page, char **start,
 			 off_t offset, int count,
 			 int *eof, void *data);
Signature · 1 line
2.32.0
#50 lore raw

PATCH v3 3/6 staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  11 +-
 drivers/staging/r8188eu/core/rtw_efuse.c      |  76 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |   9 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  13 +-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |   5 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  19 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |   4 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 ++-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 128 +++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  10 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |   8 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 267 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  18 +-
 .../staging/r8188eu/include/odm_interface.h   |   2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |   6 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  |  61 +++-
 20 files changed, 568 insertions(+), 158 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +8 -3
index 2ee64cef73f7..8b7d3eb12bd0 100644
@@ -73,8 +73,8 @@ int proc_get_read_reg(char *page, char **start,
 {
 	struct net_device *dev = data;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-
-	int len = 0;
+	u32 tmp;
+	int len = 0, error;
 
 	if (proc_get_read_addr == 0xeeeeeeee) {
 		*eof = 1;
@@ -83,7 +83,12 @@ int proc_get_read_reg(char *page, char **start,
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		error = rtw_read8(padapter, proc_get_read_addr, (u8 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
 		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_efuse.c +60 -16

153 lines not on this page · raw message

drivers/staging/r8188eu/core/rtw_io.c +3 -6
index cde0205816b1..2714506c8ffb 100644
@@ -34,18 +34,15 @@ [email protected]
 #define rtw_cpu_to_le16(val)		cpu_to_le16(val)
 #define rtw_cpu_to_le32(val)		cpu_to_le32(val)
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 {
-	u8 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl *pintfhdl = &pio_priv->intf;
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-
+	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 
 	_read8 = pintfhdl->io_ops._read8;
-	r_val = _read8(pintfhdl, addr);
 
-	return r_val;
+	return _read8(pintfhdl, addr, data);
 }
 
 u16 _rtw_read16(struct adapter *adapter, u32 addr)
drivers/staging/r8188eu/core/rtw_mp.c +11 -2
index 0a0a24fd37b0..76f0bc399819 100644
@@ -243,10 +243,14 @@ void GetPowerTracking(struct adapter *padapter, u8 *enable)
 static void disable_dm(struct adapter *padapter)
 {
 	u8 v8;
+	int error;
 
 	/* 3 1. disable firmware dynamic mechanism */
 	/*  disable Power Training, Rate Adaptive */
-	v8 = rtw_read8(padapter, REG_BCN_CTRL);
+	error = rtw_read8(padapter, REG_BCN_CTRL, &v8);
+	if (error)
+		return;
+
 	v8 &= ~EN_BCN_FUNCTION;
 	rtw_write8(padapter, REG_BCN_CTRL, v8);
 
@@ -363,8 +367,13 @@ s32 mp_start_test(struct adapter *padapter)
 	spin_unlock_bh(&pmlmepriv->lock);
 
 	if (res == _SUCCESS) {
+		int error;
 		/*  set MSR to WIFI_FW_ADHOC_STATE */
-		val8 = rtw_read8(padapter, MSR) & 0xFC; /*  0x0102 */
+		error = rtw_read8(padapter, MSR, &val8); /*  0x0102 */
+		if (error)
+			return _FAIL;
+
+		val8 &= 0xFC;
 		val8 |= WIFI_FW_ADHOC_STATE;
 		rtw_write8(padapter, MSR, val8); /*  Link in ad hoc network */
 	}
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +4 -1
index c85f8e467337..894ab456f202 100644
@@ -632,6 +632,7 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 	u32		offset, width;
 	int status = NDIS_STATUS_SUCCESS;
 	struct adapter *Adapter = (struct adapter *)(poid_par_priv->adapter_context);
+	int error;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return NDIS_STATUS_NOT_ACCEPTED;
@@ -647,7 +648,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 
 	switch (width) {
 	case 1:
-		RegRWStruct->value = rtw_read8(Adapter, offset);
+		error = rtw_read8(Adapter, offset, (u8 *) &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	case 2:
 		RegRWStruct->value = rtw_read16(Adapter, offset);
drivers/staging/r8188eu/hal/HalPhyRf_8188e.c +16 -3
index 356885e27edd..3545ad60dc00 100644
@@ -660,8 +660,12 @@ static void _PHY_SaveMACRegisters(
 	u32 i;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+	int error;
+
 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
-		MACBackup[i] = ODM_Read1Byte(dm_odm, MACReg[i]);
+		error = ODM_Read1Byte(dm_odm, MACReg[i], (u8 *) &MACBackup[i]);
+		if (error)
+			return;
 	}
 	MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
 }
@@ -1010,9 +1014,12 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
 	u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
+	int error;
 
 	/* Check continuous TX and Packet TX */
-	tmpreg = ODM_Read1Byte(dm_odm, 0xd03);
+	error = ODM_Read1Byte(dm_odm, 0xd03, &tmpreg);
+	if (error)
+		return;
 
 	if ((tmpreg & 0x70) != 0)			/* Deal with contisuous TX case */
 		ODM_Write1Byte(dm_odm, 0xd03, tmpreg & 0x8F);	/* disable all continuous TX */
@@ -1232,7 +1239,13 @@ static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2
 
 	if (!adapt->hw_init_completed) {
 		u8 u1btmp;
-		u1btmp = ODM_Read1Byte(dm_odm, REG_LEDCFG2) | BIT(7);
+		int error;
+
+		error = ODM_Read1Byte(dm_odm, REG_LEDCFG2, &u1btmp);
+		if (error)
+			return;
+
+		u1btmp |= BIT(7);
 		ODM_Write1Byte(dm_odm, REG_LEDCFG2, u1btmp);
 		ODM_SetBBReg(dm_odm, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
 	}
drivers/staging/r8188eu/hal/HalPwrSeqCmd.c +7 -2
index 0fd11aca7ac7..74e83381ef06 100644
@@ -35,6 +35,7 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 	u32 offset = 0;
 	u32 poll_count = 0; /*  polling autoload done. */
 	u32 max_poll_count = 5000;
+	int error;
 
 	do {
 		pwrcfgcmd = pwrseqcmd[aryidx];
@@ -48,7 +49,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 
 				/*  Read the value from system register */
-				value = rtw_read8(padapter, offset);
+				error = rtw_read8(padapter, offset, &value);
+				if (error)
+					return false;
 
 				value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
 				value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
@@ -60,7 +63,9 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
 				poll_bit = false;
 				offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
 				do {
-					value = rtw_read8(padapter, offset);
+					error = rtw_read8(padapter, offset, &value);
+					if (error)
+						return false;
 
 					value &= GET_PWR_CFG_MASK(pwrcfgcmd);
 					if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
drivers/staging/r8188eu/hal/hal_com.c +17 -6
index f09d4d49b159..833c88c85e3f 100644
@@ -321,11 +321,14 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 	struct c2h_evt_hdr *c2h_evt;
 	int i;
 	u8 trigger;
+	int error;
 
 	if (!buf)
 		goto exit;
 
-	trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
+	error = rtw_read8(adapter, REG_C2HEVT_CLEAR, &trigger);
+	if (error)
+		goto exit;
 
 	if (trigger == C2H_EVT_HOST_CLOSE)
 		goto exit; /* Not ready */
@@ -336,13 +339,21 @@ s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
 
 	memset(c2h_evt, 0, 16);
 
-	*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
-	*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
+	error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, buf);
+	if (error)
+		goto clear_evt;
+
+	error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, buf + 1);
+	if (error)
+		goto clear_evt;
 
 	/* Read the content */
-	for (i = 0; i < c2h_evt->plen; i++)
-		c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
-						sizeof(*c2h_evt) + i);
+	for (i = 0; i < c2h_evt->plen; i++) {
+		error = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + sizeof(*c2h_evt) + i,
+				  c2h_evt->payload + i);
+		if (error)
+			goto clear_evt;
+	}
 
 	ret = _SUCCESS;
 
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 5a01495d74bc..9a9df98da727 100644
@@ -4,10 +4,10 @@
 #include "../include/odm_precomp.h"
 /*  ODM IO Relative API. */
 
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read8(Adapter, RegAddr);
+	return rtw_read8(Adapter, RegAddr, data);
 }
 
 u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
drivers/staging/r8188eu/hal/rtl8188e_cmd.c +25 -8
index 3e1a45030bc8..53636c0e4786 100644
@@ -21,12 +21,14 @@ static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
 {
 	u8 read_down = false;
 	int	retry_cnts = 100;
-
+	int error;
 	u8 valid;
 
 	do {
-		valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
-		if (0 == valid)
+		error = rtw_read8(adapt, REG_HMETFR, &valid);
+		if (error)
+			return read_down;
+		else if (!(valid & BIT(msgbox_num)))
 			read_down = true;
 	} while ((!read_down) && (retry_cnts--));
 
@@ -578,8 +580,9 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
 	bool	bSendBeacon = false;
 	bool	bcn_valid = false;
-	u8 DLBcnCount = 0;
+	u8 DLBcnCount = 0, val8;
 	u32 poll = 0;
+	int error;
 
 	DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
 
@@ -596,8 +599,15 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  Disable Hw protection for a time which revserd for Hw sending beacon. */
 		/*  Fix download reserved page packet fail that access collision with the protection time. */
 		/*  2010.05.11. Added by tynli. */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(3)));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(4));
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 & (~BIT(3)));
+
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 | BIT(4));
 
 		if (haldata->RegFwHwTxQCtrl & BIT(6)) {
 			DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
@@ -639,8 +649,15 @@ void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
 		/*  */
 
 		/*  Enable Bcn */
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) | BIT(3));
-		rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL) & (~BIT(4)));
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 | BIT(3));
+
+		error = rtw_read8(adapt, REG_BCN_CTRL, &val8);
+		if (error)
+			return;
+		rtw_write8(adapt, REG_BCN_CTRL, val8 & (~BIT(4)));
 
 		/*  To make sure that if there exists an adapter which would like to send beacon. */
 		/*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
drivers/staging/r8188eu/hal/rtl8188e_dm.c +5 -1
index 78552303c990..5cb3d6369449 100644
@@ -16,8 +16,12 @@ static void dm_CheckStatistics(struct adapter *Adapter)
 static void dm_InitGPIOSetting(struct adapter *Adapter)
 {
 	u8	tmp1byte;
+	int error;
+
+	error = rtw_read8(Adapter, REG_GPIO_MUXCFG, &tmp1byte);
+	if (error)
+		return;
 
-	tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
 	tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
 
 	rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +99 -29

256 lines not on this page · raw message

drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +8 -2
index 30a9dca8f453..f6d4c91a97a2 100644
@@ -960,6 +960,7 @@ _PHY_SetBWMode92C(
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
 	u8 regBwOpMode;
 	u8 regRRSR_RSC;
+	int error;
 
 	if (pHalData->rf_chip == RF_PSEUDO_11N)
 		return;
@@ -975,8 +976,13 @@ _PHY_SetBWMode92C(
 	/* 3<1>Set MAC register */
 	/* 3 */
 
-	regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
-	regRRSR_RSC = rtw_read8(Adapter, REG_RRSR + 2);
+	error = rtw_read8(Adapter, REG_BWOPMODE, &regBwOpMode);
+	if (error)
+		return;
+
+	error = rtw_read8(Adapter, REG_RRSR + 2, &regRRSR_RSC);
+	if (error)
+		return;
 
 	switch (pHalData->CurrentChannelBW) {
 	case HT_CHANNEL_WIDTH_20:
drivers/staging/r8188eu/hal/rtl8188e_sreset.c +6 -2
index 16fa249e35d3..39dacfb23570 100644
@@ -49,13 +49,17 @@ void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
 {
 	u32 rx_dma_status = 0;
 	u8 fw_status = 0;
+	int error;
+
 	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
 	if (rx_dma_status != 0x00) {
 		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
 	}
-	fw_status = rtw_read8(padapter, REG_FMETHR);
-	if (fw_status != 0x00) {
+	error = rtw_read8(padapter, REG_FMETHR, &fw_status);
+	if (error) {
+		return;
+	} else if (fw_status != 0x00) {
 		if (fw_status == 1)
 			DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
 		else if (fw_status == 2)
drivers/staging/r8188eu/hal/rtl8188eu_led.c +15 -3
index 452d4bb87aba..7f793b7ce609 100644
@@ -14,10 +14,15 @@
 void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return;
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);
+
+	error = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);
+	if (error)
+		return;
+
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
 		rtw_write8(padapter, REG_LEDCFG2, (LedCfg & 0xf0) | BIT(5) | BIT(6)); /*  SW control led0 on. */
@@ -37,11 +42,14 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 {
 	u8	LedCfg;
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
+	int error;
 
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		goto exit;
 
-	LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
+	error = rtw_read8(padapter, REG_LEDCFG2, &LedCfg);/* 0x4E */
+	if (error)
+		return;
 
 	switch (pLed->LedPin) {
 	case LED_PIN_LED0:
@@ -49,7 +57,11 @@ void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
 			/*  Open-drain arrangement for controlling the LED) */
 			LedCfg &= 0x90; /*  Set to software control. */
 			rtw_write8(padapter, REG_LEDCFG2, (LedCfg | BIT(3)));
-			LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
+
+			error = rtw_read8(padapter, REG_MAC_PINMUX_CFG, &LedCfg);
+			if (error)
+				return;
+
 			LedCfg &= 0xFE;
 			rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
 		} else {
drivers/staging/r8188eu/hal/usb_halinit.c +220 -47

540 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_ops_linux.c +10 -8
index 953fa05dc30c..c4f114c3d571 100644
@@ -101,26 +101,28 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata,
 	return status;
 }
 
-static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	u8 data = 0;
-
+	int res;
 
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 1;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
-
-
-
-	return data;
+	res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 8 bytes: %d\n", res);
+		return res;
+	}
 
+	return 0;
 }
 
 static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 6b589413d56c..8e531d272927 100644
@@ -60,7 +60,7 @@ typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
 
 /*  =========== EXtern Function Prototype */
 
-u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
 u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index f1b3074fa075..fd99b36abca6 100644
@@ -85,7 +85,7 @@ struct intf_hdl;
 struct io_queue;
 
 struct _io_ops {
-	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
 	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
@@ -248,7 +248,7 @@ void unregister_intf_hdl(struct intf_hdl *pintfhdl);
 void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
-u8 _rtw_read8(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
 u16 _rtw_read16(struct adapter *adapter, u32 addr);
 u32 _rtw_read32(struct adapter *adapter, u32 addr);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
@@ -270,7 +270,7 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
 			     u8 *pmem, int timeout_ms);
 void _rtw_write_port_cancel(struct adapter *adapter);
 
-#define rtw_read8(adapter, addr) _rtw_read8((adapter), (addr))
+#define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
 #define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
 #define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
drivers/staging/r8188eu/os_dep/ioctl_linux.c +48 -13

147 lines not on this page · raw message

Signature · 1 line
2.32.0
#71 lore raw

PATCH v3 4/6 staging: r8188eu: add error handling of rtw_read16

In reply to Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  7 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  9 ++---
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  4 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 29 +++++++++++----
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  5 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 37 ++++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 22 +++++++++--
 .../staging/r8188eu/include/odm_interface.h   |  2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  6 +--
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 28 +++++++++++---
 11 files changed, 115 insertions(+), 38 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
index 8b7d3eb12bd0..a41675e101ac 100644
@@ -91,7 +91,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		error = rtw_read16(padapter, proc_get_read_addr, (u16 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n",
+				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
 		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_io.c +3 -6
index 2714506c8ffb..fd64893c778d 100644
@@ -45,18 +45,15 @@ int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 	return _read8(pintfhdl, addr, data);
 }
 
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 {
-	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 
 	_read16 = pintfhdl->io_ops._read16;
 
-	r_val = _read16(pintfhdl, addr);
-
-	return r_val;
+	return _read16(pintfhdl, addr, data);
 }
 
 u32 _rtw_read32(struct adapter *adapter, u32 addr)
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +3 -1
index 894ab456f202..c6f7636c2174 100644
@@ -653,7 +653,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	case 2:
-		RegRWStruct->value = rtw_read16(Adapter, offset);
+		error = rtw_read16(Adapter, offset, (u16 *) &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	default:
 		width = 4;
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 9a9df98da727..669d3e5eafb6 100644
@@ -10,10 +10,10 @@ int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data)
 	return rtw_read8(Adapter, RegAddr, data);
 }
 
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read16(Adapter, RegAddr);
+	return rtw_read16(Adapter, RegAddr, data);
 }
 
 u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +21 -8
index cfc429965b7d..94e2828c328e 100644
@@ -262,7 +262,11 @@ static void efuse_read_phymap_from_txpktbuf(
 			 * do not remove it as the rtw_read16() call consumes
 			 * 2 bytes from the EEPROM source.
 			 */
-			u16 lenc = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
+			u16 lenc;
+
+			error = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, &lenc);
+			if (error)
+				return;
 
 			len = le32_to_cpu(lo32) & 0x0000ffff;
 
@@ -778,21 +782,27 @@ hal_EfusePowerSwitch_RTL8188E(
 		rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
 
 		/*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
-		if (!(tmpV16 & PWC_EV12V)) {
+		error = rtw_read16(pAdapter, REG_SYS_ISO_CTRL, &tmpV16);
+		if (error) {
+			return;
+		} else if (!(tmpV16 & PWC_EV12V)) {
 			tmpV16 |= PWC_EV12V;
 			rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
 		}
 		/*  Reset: 0x0000h[28], default valid */
-		tmpV16 =  rtw_read16(pAdapter, REG_SYS_FUNC_EN);
-		if (!(tmpV16 & FEN_ELDR)) {
+		error = rtw_read16(pAdapter, REG_SYS_FUNC_EN, &tmpV16);
+		if (error) {
+			return;
+		} else if (!(tmpV16 & FEN_ELDR)) {
 			tmpV16 |= FEN_ELDR;
 			rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
 		}
 
 		/*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
-		tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
-		if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
+		error = rtw_read16(pAdapter, REG_SYS_CLKR, &tmpV16);
+		if (error) {
+			return;
+		} else if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
 			tmpV16 |= (LOADER_CLK_EN | ANA8M);
 			rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
 		}
@@ -1915,8 +1925,11 @@ u8 GetEEPROMSize8188E(struct adapter *padapter)
 {
 	u8 size = 0;
 	u32	cr;
+	int error;
 
-	cr = rtw_read16(padapter, REG_9346CR);
+	error = rtw_read16(padapter, REG_9346CR, (u16 *) &cr);
+	if (error)
+		return size;
 	/*  6: EEPROM used is 93C46, 4: boot from E-Fuse. */
 	size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
 
drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +4 -1
index f6d4c91a97a2..3afb66195413 100644
@@ -577,11 +577,14 @@ PHY_BBConfig8188E(
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(Adapter);
 	u32 RegVal;
 	u8 CrystalCap;
+	int error;
 
 	phy_InitBBRFRegisterDefinition(Adapter);
 
 	/*  Enable BB and RF */
-	RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+	error = rtw_read16(Adapter, REG_SYS_FUNC_EN, (u16 *) &RegVal);
+	if (error)
+		return _FAIL;
 	rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1)));
 
 	/*  20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
drivers/staging/r8188eu/hal/usb_halinit.c +32 -5
index 4f1d7f9b43c3..4ecccc6499aa 100644
@@ -90,6 +90,8 @@ static u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
 	u16 value16;
 	/*  HW Power on sequence */
 	struct hal_data_8188e	*haldata	= GET_HAL_DATA(adapt);
+	int error;
+
 	if (haldata->bMacPwrCtrlOn)
 		return _SUCCESS;
 
@@ -103,7 +105,10 @@ static u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
 	rtw_write16(adapt, REG_CR, 0x00);  /* suggseted by zhouzhou, by page, 20111230 */
 
 		/*  Enable MAC DMA/WMAC/SCHEDULE/SEC block */
-	value16 = rtw_read16(adapt, REG_CR);
+	error = rtw_read16(adapt, REG_CR, &value16);
+	if (error)
+		return _FAIL;
+
 	value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
 				| PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
 	/*  for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
@@ -207,7 +212,14 @@ static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
 				       u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
 				       u16 hiQ)
 {
-	u16 value16	= (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+	u16 value16;
+	int error;
+
+	error = rtw_read16(Adapter, REG_TRXDMA_CTRL, &value16);
+	if (error)
+		return;
+
+	value16 &= 0x7;
 
 	value16 |= _TXDMA_BEQ_MAP(beQ)	| _TXDMA_BKQ_MAP(bkQ) |
 		   _TXDMA_VIQ_MAP(viQ)	| _TXDMA_VOQ_MAP(voQ) |
@@ -868,7 +880,12 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 	/*  Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
 	/*  */
 	/*  Enable MACTXEN/MACRXEN block */
-	value16 = rtw_read16(Adapter, REG_CR);
+	error = rtw_read16(Adapter, REG_CR, &value16);
+	if (error) {
+		status = _FAIL;
+		goto exit;
+	}
+
 	value16 |= (MACTXEN | MACRXEN);
 	rtw_write8(Adapter, REG_CR, value16);
 
@@ -937,6 +954,8 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 		Adapter->mppriv.channel = haldata->CurrentChannel;
 		MPT_InitializeAdapter(Adapter, Adapter->mppriv.channel);
 	} else {
+		u16 val16;
+
 		/*  2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
 		/*  and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
 		/*  call initstruct adapter. May cause some problem?? */
@@ -956,7 +975,13 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
 		rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
 
 		/* enable tx DMA to drop the redundate data of packet */
-		rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+		error = rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK, &val16);
+		if (error) {
+			status = _FAIL;
+			goto exit;
+		}
+
+		rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (val16 | DROP_DATA_EN));
 
 		HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
 		/*  2010/08/26 MH Merge from 8192CE. */
@@ -1982,7 +2007,9 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 			rtw_write8(Adapter, REG_TXPAUSE, 0xff);
 
 			/* keep sn */
-			Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
+			error = rtw_read16(Adapter, REG_NQOS_SEQ, &Adapter->xmitpriv.nqos_ssn);
+			if (error)
+				return;
 
 			if (!pwrpriv->bkeepfwalive) {
 				/* RX DMA stop */
drivers/staging/r8188eu/hal/usb_ops_linux.c +18 -4
index c4f114c3d571..f713ee4bdbc8 100644
@@ -125,19 +125,33 @@ static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data)
 	return 0;
 }
 
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 2;
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 16 bytes: %d\n", res);
+		return res;
+	} else if (res != len) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev),
+			"Failed to read 16 bytes, could read only %d bytes\n", res);
+		return -EIO;
+	}
 
-	return (u16)(le32_to_cpu(data) & 0xffff);
+	*data = le32_to_cpu(tmp) & 0xffff;
+
+	return 0;
 }
 
 static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 8e531d272927..2455dae6eebb 100644
@@ -62,7 +62,7 @@ typedef void (*RT_WORKITEM_CALL_BACK)(void *pContext);
 
 int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
-u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data);
 
 u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index fd99b36abca6..c44554c848cf 100644
@@ -86,7 +86,7 @@ struct io_queue;
 
 struct _io_ops {
 	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
@@ -249,7 +249,7 @@ void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
 int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
-u16 _rtw_read16(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data);
 u32 _rtw_read32(struct adapter *adapter, u32 addr);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
@@ -271,7 +271,7 @@ u32 _rtw_write_port_and_wait(struct adapter *adapter, u32 addr, u32 cnt,
 void _rtw_write_port_cancel(struct adapter *adapter);
 
 #define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
-#define rtw_read16(adapter, addr) _rtw_read16((adapter), (addr))
+#define rtw_read16(adapter, addr, data) _rtw_read16((adapter), (addr), (data))
 #define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
 	_rtw_read_mem((adapter), (addr), (cnt), (mem))
drivers/staging/r8188eu/os_dep/ioctl_linux.c +22 -6
index c9f0772bcbe1..79f0fbaa841e 100644
@@ -2101,7 +2101,10 @@ static int rtw_wx_read32(struct net_device *dev,
 		sprintf(extra, "0x%02X", data32);
 		break;
 	case 2:
-		data32 = rtw_read16(padapter, addr);
+		error = rtw_read16(padapter, addr, (u16 *) &data32);
+		if (error)
+			return error;
+
 		sprintf(extra, "0x%04X", data32);
 		break;
 	case 4:
@@ -2271,7 +2274,8 @@ static void rtw_dbg_mode_hdl(struct adapter *padapter, u32 id, u8 *pdata, u32 le
 					 (u8 *) &RegRWStruct->value);
 			break;
 		case 2:
-			RegRWStruct->value = rtw_read16(padapter, RegRWStruct->offset);
+			error = rtw_read16(padapter, RegRWStruct->offset,
+					  (u16 *) &RegRWStruct->value);
 			break;
 		case 4:
 			RegRWStruct->value = rtw_read32(padapter, RegRWStruct->offset);
@@ -3990,7 +3994,8 @@ static int rtw_dbg_port(struct net_device *dev,
 				DBG_88E("rtw_read8(0x%x) = 0x%02x\n", arg, (u8) tmp);
 			break;
 		case 2:
-			DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+			if (!rtw_read16(padapter, arg, (u16 *) &tmp))
+				DBG_88E("rtw_read16(0x%x) = 0x%04x\n", arg, (u16) tmp);
 			break;
 		case 4:
 			DBG_88E("rtw_read32(0x%x) = 0x%08x\n", arg, rtw_read32(padapter, arg));
@@ -4006,8 +4011,12 @@ static int rtw_dbg_port(struct net_device *dev,
 
 			break;
 		case 2:
+			error = rtw_read16(padapter, arg, (u16 *) &tmp);
+			if (error)
+				return error;
+
 			rtw_write16(padapter, arg, extra_arg);
-			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, rtw_read16(padapter, arg));
+			DBG_88E("rtw_write16(0x%x) = 0x%04x\n", arg, (u16) tmp);
 			break;
 		case 4:
 			rtw_write32(padapter, arg, extra_arg);
@@ -4138,7 +4147,10 @@ static int rtw_dbg_port(struct net_device *dev,
 			if (_SUCCESS != rtw_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0))
 				ret = -EPERM;
 
-			final = rtw_read16(padapter, reg);
+			error = rtw_read16(padapter, reg, &final);
+			if (error)
+				return error;
+
 			if (start_value + write_num - 1 == final)
 				DBG_88E("continuous IOL_CMD_WW_REG to 0x%x %u times Success, start:%u, final:%u\n", reg, write_num, start_value, final);
 			else
@@ -5387,7 +5399,11 @@ static int rtw_mp_read_reg(struct net_device *dev,
 		break;
 	case 'w':
 		/*  2 bytes */
-		sprintf(data, "%04x\n", rtw_read16(padapter, addr));
+		error = rtw_read16(padapter, addr, (u16 *) &val32);
+		if (error)
+			return error;
+
+		sprintf(data, "%04x\n", (u16) val32);
 		for (i = 0; i <= strlen(data); i++) {
 			if (i % 2 == 0) {
 				tmp[j] = ' ';
Signature · 1 line
2.32.0
#87 lore raw

PATCH v3 5/6 staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  61 +++++++--
 drivers/staging/r8188eu/core/rtw_efuse.c      |  14 ++-
 drivers/staging/r8188eu/core/rtw_io.c         |   9 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  18 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |   4 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |   2 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |   4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   |  63 ++++++++--
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  14 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 119 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  22 +++-
 .../staging/r8188eu/include/odm_interface.h   |   2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |   6 +-
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  |  90 ++++++++-----
 18 files changed, 357 insertions(+), 105 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +54 -7
index a41675e101ac..c76feb44ecfa 100644
@@ -99,7 +99,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
-		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+		error = rtw_read32(padapter, proc_get_read_addr, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n",
+				proc_get_read_addr, tmp);
 		break;
 	default:
 		len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
@@ -315,13 +320,20 @@ int proc_get_mac_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x0; i < 0x300; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -338,13 +350,20 @@ int proc_get_mac_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 	memset(page, 0, count);
 	for (i = 0x300; i < 0x600; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -361,13 +380,20 @@ int proc_get_mac_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= MAC REG =======\n");
 
 	for (i = 0x600; i < 0x800; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return error;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -384,12 +410,19 @@ int proc_get_bb_reg_dump1(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0x800; i < 0xB00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -405,12 +438,19 @@ int proc_get_bb_reg_dump2(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xB00; i < 0xE00; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
@@ -426,12 +466,19 @@ int proc_get_bb_reg_dump3(char *page, char **start,
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 	int len = 0;
 	int i, j = 1;
+	int error;
+	u32 tmp;
 
 	len += snprintf(page + len, count - len, "\n======= BB REG =======\n");
 	for (i = 0xE00; i < 0x1000; i += 4) {
 		if (j % 4 == 1)
 			len += snprintf(page + len, count - len, "0x%02x", i);
-		len += snprintf(page + len, count - len, " 0x%08x ", rtw_read32(padapter, i));
+
+		error = rtw_read32(padapter, i, &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, " 0x%08x ", tmp);
 		if ((j++) % 4 == 0)
 			len += snprintf(page + len, count - len, "\n");
 	}
drivers/staging/r8188eu/core/rtw_efuse.c +11 -3
index b471f6446f78..dfe60bc6a547 100644
@@ -183,9 +183,15 @@ ReadEFuseByte(
 
 	/* Check bit 32 read-ready */
 	retry = 0;
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+	if (error)
+		return;
+
 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
-		value32 = rtw_read32(Adapter, EFUSE_CTRL);
+		error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+		if (error)
+			return;
+
 		retry++;
 	}
 
@@ -194,7 +200,9 @@ ReadEFuseByte(
 	/*  Designer says that there shall be some delay after ready bit is set, or the */
 	/*  result will always stay on last data we read. */
 	udelay(50);
-	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
+	if (error)
+		return;
 
 	*pbuf = (u8)(value32 & 0xff);
 }
drivers/staging/r8188eu/core/rtw_io.c +3 -6
index fd64893c778d..df4d8ac8aadc 100644
@@ -56,18 +56,15 @@ int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 	return _read16(pintfhdl, addr, data);
 }
 
-u32 _rtw_read32(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read32(struct adapter *adapter, u32 addr, u32 *data)
 {
-	u32 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u32	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	int	(*_read32)(struct intf_hdl *pintfhdl, u32 addr, u32 *data);
 
 	_read32 = pintfhdl->io_ops._read32;
 
-	r_val = _read32(pintfhdl, addr);
-
-	return r_val;
+	return _read32(pintfhdl, addr, data);
 }
 
 int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
drivers/staging/r8188eu/core/rtw_mp.c +15 -3
index 76f0bc399819..e990e81966af 100644
@@ -765,12 +765,17 @@ static u32 GetPhyRxPktCounts(struct adapter *pAdapter, u32 selbit)
 {
 	/* selection */
 	u32 phyrx_set = 0, count = 0;
+	int error;
 
 	phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
 	rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
 
 	/* Read packet count */
-	count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
+	error = rtw_read32(pAdapter, REG_RXERR_RPT, &count);
+	if (error)
+		return count;
+
+	count &= RXERR_COUNTER_MASK;
 
 	return count;
 }
@@ -803,8 +808,12 @@ u32 GetPhyRxPktCRC32Error(struct adapter *pAdapter)
 static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 {
 	int psd_val;
+	int error;
+
+	error = rtw_read32(pAdapter, 0x808, &psd_val);
+	if (error)
+		return 0;
 
-	psd_val = rtw_read32(pAdapter, 0x808);
 	psd_val &= 0xFFBFFC00;
 	psd_val |= point;
 
@@ -814,7 +823,10 @@ static u32 rtw_GetPSDData(struct adapter *pAdapter, u32 point)
 
 	rtw_write32(pAdapter, 0x808, psd_val);
 	mdelay(1);
-	psd_val = rtw_read32(pAdapter, 0x8B4);
+
+	error = rtw_read32(pAdapter, 0x8B4, &psd_val);
+	if (error)
+		return 0;
 
 	psd_val &= 0x0000FFFF;
 
drivers/staging/r8188eu/core/rtw_mp_ioctl.c +3 -1
index c6f7636c2174..9eaef9c73516 100644
@@ -659,7 +659,9 @@ int rtl8188eu_oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
 		break;
 	default:
 		width = 4;
-		RegRWStruct->value = rtw_read32(Adapter, offset);
+		error = rtw_read32(Adapter, offset, &RegRWStruct->value);
+		if (error)
+			status = NDIS_STATUS_NOT_ACCEPTED;
 		break;
 	}
 
drivers/staging/r8188eu/core/rtw_pwrctrl.c +4 -1
index c3897b29121c..4335907acbc3 100644
@@ -55,6 +55,7 @@ int ips_leave(struct adapter *padapter)
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 	int result = _SUCCESS;
 	int keyid;
+	u32 tmp;
 
 	_enter_pwrlock(&pwrpriv->lock);
 
@@ -83,7 +84,9 @@ int ips_leave(struct adapter *padapter)
 			}
 		}
 
-		DBG_88E("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
+		if (!rtw_read32(padapter, 0x4c, &tmp))
+			DBG_88E("==> ips_leave.....LED(0x%08x)...\n", tmp);
+
 		pwrpriv->bips_processing = false;
 
 		pwrpriv->bkeepfwalive = false;
drivers/staging/r8188eu/core/rtw_sreset.c +7 -2
index 8e1bc62e74e5..ec5d070e1641 100644
@@ -29,13 +29,18 @@ u8 sreset_get_wifi_status(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	u8 status = WIFI_STATUS_SUCCESS;
 	u32 val32 = 0;
 
 	if (psrtpriv->silent_reset_inprogress)
 		return status;
-	val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
+	error = rtw_read32(padapter, REG_TXDMA_STATUS, &val32);
+	if (error) {
+		psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
+		return WIFI_MAC_TXDMA_ERROR;
+	}
+
 	if (val32 == 0xeaeaeaea) {
 		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
 	} else if (val32 != 0) {
drivers/staging/r8188eu/hal/Hal8188ERateAdaptive.c +4 -4
index d873672feb27..bd4580eba0a9 100644
@@ -316,19 +316,19 @@ static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_inf
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & 0x0000000d;
 		break;
 	case 12:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR0);
+		ODM_Read4Byte(dm_odm, REG_ARFR0, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 13:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR1);
+		ODM_Read4Byte(dm_odm, REG_ARFR1, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 14:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR2);
+		ODM_Read4Byte(dm_odm, REG_ARFR2, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	case 15:
-		MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR3);
+		ODM_Read4Byte(dm_odm, REG_ARFR3, &MaskFromReg);
 		pRaInfo->RAUseRate = (pRaInfo->RateMask) & MaskFromReg;
 		break;
 	default:
drivers/staging/r8188eu/hal/HalPhyRf_8188e.c +1 -1
index 3545ad60dc00..725a18dc3979 100644
@@ -667,7 +667,7 @@ static void _PHY_SaveMACRegisters(
 		if (error)
 			return;
 	}
-	MACBackup[i] = ODM_Read4Byte(dm_odm, MACReg[i]);
+	ODM_Read4Byte(dm_odm, MACReg[i], MACBackup + i);
 }
 
 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
drivers/staging/r8188eu/hal/odm_interface.c +2 -2
index 669d3e5eafb6..a47319dec231 100644
@@ -16,10 +16,10 @@ int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data)
 	return rtw_read16(Adapter, RegAddr, data);
 }
 
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
+int ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 *data)
 {
 	struct adapter *Adapter = pDM_Odm->Adapter;
-	return rtw_read32(Adapter, RegAddr);
+	return rtw_read32(Adapter, RegAddr, data);
 }
 
 void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +51 -12

126 lines not on this page · raw message

drivers/staging/r8188eu/hal/rtl8188e_phycfg.c +10 -2
index 3afb66195413..24b2afb62d68 100644
@@ -75,8 +75,12 @@ rtl8188e_PHY_QueryBBReg(
 	)
 {
 	u32 ReturnValue = 0, OriginalValue, BitShift;
+	int error;
+
+	error = rtw_read32(Adapter, RegAddr, &OriginalValue);
+	if (error)
+		return ReturnValue;
 
-	OriginalValue = rtw_read32(Adapter, RegAddr);
 	BitShift = phy_CalculateBitShift(BitMask);
 	ReturnValue = (OriginalValue & BitMask) >> BitShift;
 	return ReturnValue;
@@ -103,9 +107,13 @@ rtl8188e_PHY_QueryBBReg(
 void rtl8188e_PHY_SetBBReg(struct adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
 {
 	u32 OriginalValue, BitShift;
+	int error;
 
 	if (BitMask != bMaskDWord) { /* if not "double word" write */
-		OriginalValue = rtw_read32(Adapter, RegAddr);
+		error = rtw_read32(Adapter, RegAddr, &OriginalValue);
+		if (error)
+			return;
+
 		BitShift = phy_CalculateBitShift(BitMask);
 		Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
 	}
drivers/staging/r8188eu/hal/rtl8188e_sreset.c +9 -5
index 39dacfb23570..a023a0669ffd 100644
@@ -14,14 +14,16 @@ void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(padapter);
 	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
-
+	int error;
 	unsigned long current_time;
 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
 	unsigned int diff_time;
 	u32 txdma_status;
 
-	txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
-	if (txdma_status != 0x00) {
+	error = rtw_read32(padapter, REG_TXDMA_STATUS, &txdma_status);
+	if (error) {
+		return;
+	} else if (txdma_status != 0x00) {
 		DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
 		rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
 		rtl8188e_silentreset_for_specific_platform(padapter);
@@ -51,8 +53,10 @@ void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
 	u8 fw_status = 0;
 	int error;
 
-	rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
-	if (rx_dma_status != 0x00) {
+	error = rtw_read32(padapter, REG_RXDMA_STATUS, &rx_dma_status);
+	if (error) {
+		return;
+	} else if (rx_dma_status != 0x00) {
 		DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
 		rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
 	}
drivers/staging/r8188eu/hal/usb_halinit.c +100 -19

252 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_ops_linux.c +18 -4
index f713ee4bdbc8..b82dd3e16200 100644
@@ -154,21 +154,35 @@ static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 	return 0;
 }
 
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+		return res;
+	} else if (res != len) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev),
+			"Failed to read 32 bytes, could read only %d bytes\n", res);
+		return -EIO;
+	}
+
+	*data = le32_to_cpu(tmp);
 
-	return le32_to_cpu(data);
+	return 0;
 }
 
 static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
drivers/staging/r8188eu/include/odm_interface.h +1 -1
index 2455dae6eebb..bbb1045c9e7d 100644
@@ -64,7 +64,7 @@ int ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 *data);
 
 int ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 *data);
 
-u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr);
+int ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 *data);
 
 void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data);
 
drivers/staging/r8188eu/include/rtw_io.h +3 -3
index c44554c848cf..501168457518 100644
@@ -87,7 +87,7 @@ struct io_queue;
 struct _io_ops {
 	int (*_read8)(struct intf_hdl *pintfhdl, u32 addr, u8 *data);
 	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
-	u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read32)(struct intf_hdl *pintfhdl, u32 addr, u32 *data);
 	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
 	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
 	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
@@ -250,7 +250,7 @@ void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 
 int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
 int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data);
-u32 _rtw_read32(struct adapter *adapter, u32 addr);
+int __must_check _rtw_read32(struct adapter *adapter, u32 addr, u32 *data);
 void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
 void _rtw_read_port_cancel(struct adapter *adapter);
@@ -272,7 +272,7 @@ void _rtw_write_port_cancel(struct adapter *adapter);
 
 #define rtw_read8(adapter, addr, data) _rtw_read8((adapter), (addr), (data))
 #define rtw_read16(adapter, addr, data) _rtw_read16((adapter), (addr), (data))
-#define rtw_read32(adapter, addr) _rtw_read32((adapter), (addr))
+#define rtw_read32(adapter, addr, data) _rtw_read32((adapter), (addr), (data))
 #define rtw_read_mem(adapter, addr, cnt, mem)				\
 	_rtw_read_mem((adapter), (addr), (cnt), (mem))
 #define rtw_read_port(adapter, addr, cnt, mem)				\
drivers/staging/r8188eu/os_dep/ioctl_linux.c +61 -29

195 lines not on this page · raw message

Signature · 1 line
2.32.0
#98 lore raw

PATCH v3 6/6 staging: r8188eu: make ReadEFuse return an int

In reply to Pavel Skripkin

ReadEFuse can fail in case of _rtw_read() failure. Callers should handle this error to avoid uninit value bugs, since ReadEFuse won't initialized passed pbuf in case of usb transfer failure.

To achieve it, ReadEFuseByte() now returns an int and all callers of ReadEFuseByte() passes error code up to calltrace to rtw_usb_if1_init(), which fails when reading regiters fails.

---
 drivers/staging/r8188eu/core/rtw_efuse.c      | 45 ++++++++-----
 drivers/staging/r8188eu/hal/hal_intf.c        |  6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 65 ++++++++++++-------
 drivers/staging/r8188eu/hal/usb_halinit.c     | 18 +++--
 drivers/staging/r8188eu/include/hal_intf.h    |  6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |  2 +-
 drivers/staging/r8188eu/include/rtw_efuse.h   |  4 +-
 drivers/staging/r8188eu/os_dep/usb_intf.c     |  3 +-
 8 files changed, 96 insertions(+), 53 deletions(-)
drivers/staging/r8188eu/core/rtw_efuse.c +30 -15
index dfe60bc6a547..5bfcf80b2678 100644
@@ -149,7 +149,7 @@ Efuse_CalculateWordCnts(u8 word_en)
 /*  */
 /* 	Created by Roger, 2008.10.21. */
 /*  */
-void
+int
 ReadEFuseByte(
 		struct adapter *Adapter,
 		u16 _offset,
@@ -163,21 +163,21 @@ ReadEFuseByte(
 
 	if (pseudo) {
 		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
-		return;
+		return 0;
 	}
 
 	/* Write Address */
 	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
 	error = rtw_read8(Adapter, EFUSE_CTRL + 2, &readbyte);
 	if (error)
-		return;
+		return error;
 
 	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 
 	/* Write bit 32 0 */
 	error = rtw_read8(Adapter, EFUSE_CTRL + 3, &readbyte);
 	if (error)
-		return;
+		return error;
 
 	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
 
@@ -185,12 +185,12 @@ ReadEFuseByte(
 	retry = 0;
 	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 	if (error)
-		return;
+		return error;
 
 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
 		error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 		if (error)
-			return;
+			return error;
 
 		retry++;
 	}
@@ -202,9 +202,11 @@ ReadEFuseByte(
 	udelay(50);
 	error = rtw_read32(Adapter, EFUSE_CTRL, &value32);
 	if (error)
-		return;
+		return error;
 
 	*pbuf = (u8)(value32 & 0xff);
+
+	return 0;
 }
 
 /*  */
@@ -225,9 +227,9 @@ ReadEFuseByte(
 /* 					write addr must be after sec5. */
 /*  */
 
-static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
+static int efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
 {
-	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
+	return Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
 }
 
 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
@@ -538,6 +540,7 @@ u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int error;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -546,7 +549,9 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	error = efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+	if (error)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -556,6 +561,7 @@ u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
 	u16 mapLen = 0;
+	int error;
 
 	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 
@@ -564,7 +570,9 @@ u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
 	Efuse_PowerSwitch(padapter, false, true);
 
-	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	error = efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
+	if (error)
+		return _FAIL;
 
 	Efuse_PowerSwitch(padapter, false, false);
 
@@ -835,17 +843,22 @@ efuse_ShadowRead4Byte(
  * 11/11/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+static int Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
 {
 	u16 mapLen = 0;
+	int error;
 
 	Efuse_PowerSwitch(pAdapter, false, true);
 
 	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 
-	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	error = efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+	if (error)
+		return error;
 
 	Efuse_PowerSwitch(pAdapter, false, false);
+
+	return 0;
 }
 
 /*-----------------------------------------------------------------------------
@@ -864,7 +877,7 @@ static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse,
  * 11/13/2008	MHC		Create Version 0.
  *
  *---------------------------------------------------------------------------*/
-void EFUSE_ShadowMapUpdate(
+int EFUSE_ShadowMapUpdate(
 	struct adapter *pAdapter,
 	u8 efuseType,
 	bool pseudo)
@@ -877,7 +890,9 @@ void EFUSE_ShadowMapUpdate(
 	if (pEEPROM->bautoload_fail_flag)
 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 	else
-		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+		return Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
+
+	return 0;
 } /*  EFUSE_ShadowMapUpdate */
 
 /*-----------------------------------------------------------------------------
drivers/staging/r8188eu/hal/hal_intf.c +4 -2
index a6d589e89aeb..dce9a58eaf6f 100644
@@ -12,10 +12,12 @@ void rtw_hal_chip_configure(struct adapter *adapt)
 		adapt->HalFunc.intf_chip_configure(adapt);
 }
 
-void rtw_hal_read_chip_info(struct adapter *adapt)
+int rtw_hal_read_chip_info(struct adapter *adapt)
 {
 	if (adapt->HalFunc.read_adapter_info)
-		adapt->HalFunc.read_adapter_info(adapt);
+		return adapt->HalFunc.read_adapter_info(adapt);
+
+	return _FAIL;
 }
 
 void rtw_hal_read_chip_version(struct adapter *adapt)
drivers/staging/r8188eu/hal/rtl8188e_hal_init.c +42 -23

173 lines not on this page · raw message

drivers/staging/r8188eu/hal/usb_halinit.c +12 -6
index 3826476e3396..687baf4d9d97 100644
@@ -1296,7 +1296,7 @@ readAdapterInfo_8188EU(
 	_ReadLEDSetting(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
 }
 
-static void _ReadPROMContent(
+static int _ReadPROMContent(
 	struct adapter *Adapter
 	)
 {
@@ -1307,7 +1307,7 @@ static void _ReadPROMContent(
 	/* check system boot selection */
 	error = rtw_read8(Adapter, REG_9346CR, &eeValue);
 	if (error)
-		return;
+		return error;
 
 	eeprom->EepromOrEfuse		= (eeValue & BOOT_FROM_EEPROM) ? true : false;
 	eeprom->bautoload_fail_flag	= (eeValue & EEPROM_EN) ? false : true;
@@ -1315,8 +1315,13 @@ static void _ReadPROMContent(
 	DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"),
 		(eeprom->bautoload_fail_flag ? "Fail" : "OK"));
 
-	Hal_InitPGData88E(Adapter);
+	error = Hal_InitPGData88E(Adapter);
+	if (error)
+		return error;
+
 	readAdapterInfo_8188EU(Adapter);
+
+	return 0;
 }
 
 static void _ReadRFType(struct adapter *Adapter)
@@ -1333,19 +1338,20 @@ static int _ReadAdapterInfo8188EU(struct adapter *Adapter)
 	MSG_88E("====> %s\n", __func__);
 
 	_ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
-	_ReadPROMContent(Adapter);
+	if (_ReadPROMContent(Adapter))
+		return _FAIL;
 
 	MSG_88E("<==== %s in %d ms\n", __func__, rtw_get_passing_time_ms(start));
 
 	return _SUCCESS;
 }
 
-static void ReadAdapterInfo8188EU(struct adapter *Adapter)
+static int ReadAdapterInfo8188EU(struct adapter *Adapter)
 {
 	/*  Read EEPROM size before call any EEPROM function */
 	Adapter->EepromAddressSize = GetEEPROMSize8188E(Adapter);
 
-	_ReadAdapterInfo8188EU(Adapter);
+	return _ReadAdapterInfo8188EU(Adapter);
 }
 
 #define GPIO_DEBUG_PORT_NUM 0
drivers/staging/r8188eu/include/hal_intf.h +3 -3
index fa252540e596..9241af39e3a3 100644
@@ -154,7 +154,7 @@ struct hal_ops {
 
 	void	(*intf_chip_configure)(struct adapter *padapter);
 
-	void	(*read_adapter_info)(struct adapter *padapter);
+	int	(*read_adapter_info)(struct adapter *padapter);
 
 	void	(*enable_interrupt)(struct adapter *padapter);
 	void	(*disable_interrupt)(struct adapter *padapter);
@@ -222,7 +222,7 @@ struct hal_ops {
 
 	void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite,
 				 u8 PwrState);
-	void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
+	int (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset,
 			  u16 _size_byte, u8 *pbuf, bool bPseudoTest);
 	void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType,
 					u8 type, void *pOut, bool bPseudoTest);
@@ -324,7 +324,7 @@ void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
 
 void rtw_hal_chip_configure(struct adapter *padapter);
-void rtw_hal_read_chip_info(struct adapter *padapter);
+int rtw_hal_read_chip_info(struct adapter *padapter);
 void rtw_hal_read_chip_version(struct adapter *padapter);
 
 u8 rtw_hal_set_def_var(struct adapter *padapter,
drivers/staging/r8188eu/include/rtl8188e_hal.h +1 -1
index 3939bf053de1..db9adbd0b024 100644
@@ -410,7 +410,7 @@ s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy);
 
 /*  EFuse */
 u8 GetEEPROMSize8188E(struct adapter *padapter);
-void Hal_InitPGData88E(struct adapter *padapter);
+int Hal_InitPGData88E(struct adapter *padapter);
 void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo);
 void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo,
 			    bool AutoLoadFail);
drivers/staging/r8188eu/include/rtw_efuse.h +2 -2
index b3ff46db2091..9657b66679e3 100644
@@ -113,7 +113,7 @@ u8 rtw_BT_efuse_map_write(struct adapter *adapter, u16 addr,
 			  u16 cnts, u8 *data);
 u16 Efuse_GetCurrentSize(struct adapter *adapter, u8 efusetype, bool test);
 u8 Efuse_CalculateWordCnts(u8 word_en);
-void ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
+int ReadEFuseByte(struct adapter *adapter, u16 _offset, u8 *pbuf, bool test);
 void EFUSE_GetEfuseDefinition(struct adapter *adapt, u8 type, u8 type1,
 			      void *out, bool bPseudoTest);
 u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data, bool test);
@@ -128,7 +128,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
 			     u8 word_en, u8 *data, bool test);
 
 u8 EFUSE_Read1Byte(struct adapter *adapter, u16 address);
-void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
+int EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype, bool test);
 void EFUSE_ShadowRead(struct adapter *adapt, u8 type, u16 offset, u32 *val);
 
 #endif
drivers/staging/r8188eu/os_dep/usb_intf.c +2 -1
index e002070f7fba..7a1a296f66b5 100644
@@ -608,7 +608,8 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
 	rtw_hal_chip_configure(padapter);
 
 	/* step read efuse/eeprom data and get mac_addr */
-	rtw_hal_read_chip_info(padapter);
+	if (rtw_hal_read_chip_info(padapter) == _FAIL)
+		goto free_hal_data;
 
 	/* step 5. */
 	if (rtw_init_drv_sw(padapter) == _FAIL)
Signature · 1 line
2.32.0
#37 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 83 lines · CEST Pavel Skripkin
Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Quoted 8 lines

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Hi Pavel,

I (wrongly?) assumed from the prototype of usb_read32() that u32 *data is in native endianness. So, I didn't see the necessity of using _le32 tmp and then convert that tmp with le32_to_cpu().

I simply thought that data could be passed to usbctrl_vendorreq as it-is.

Quoted 3 lines

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

Now that you explained that "Data from chip comes in little-endian", obviously I must agree with you that the code needs tmp and that tmp must be swapped by le32_to_cpu(), ahead of assigning it to *data.

Just a curiosity... Since I was not able to see that *data is returned in little endian, can you please point me where in the code you found out that it is? There must be some place in the code that I'm unable to find and see that *data is LE.

Thanks in advance,

Fabio

Quoted 6 lines

If I am missing something, please, let me know :) v3 is on the way...

With regards,
Pavel Skripkin

#38 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 105 lines · Fabio M. De Francesco
Quoted 83 lines · CEST Pavel Skripkin
Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Quoted 6 lines

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Hi Pavel,

I (wrongly?) assumed from the prototype of usb_read32() that u32 *data is in native endianness. So, I didn't see the necessity of using _le32 tmp and then convert that tmp with le32_to_cpu().

I simply thought that data could be passed to usbctrl_vendorreq as it-is.

Quoted 1 line

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

Now that you explained that "Data from chip comes in little-endian", obviously I must agree with you that the code needs tmp and that tmp must be swapped by le32_to_cpu(), ahead of assigning it to *data.

Quoted 7 lines

Just a curiosity... Since I was not able to see that *data is returned in little endian, can you please point me where in the code you found out that it is? There must be some place in the code that I'm unable to find and see that *data is LE.

Thanks in advance,

Fabio

Hi, Fabio!

previous usb_read16() realization, which is 100% right:

static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)

{
	u8 requesttype;
	u16 wvalue;
	u16 len;
	__le32 data;

	requesttype = 0x01;/* read_in */
	wvalue = (u16)(addr & 0x0000ffff);
	len = 2;
	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

	return (u16)(le32_to_cpu(data) & 0xffff);
}

Bases on this code, I think, it's oblivious, that data comes in little-endian. That's why I leaved temp variable for casting le32 to cpu's endianess.

I could just read into u{16,32} * and then make smth like

*data = le32_to_cpu(*data)

but static analysis tools will complain about wrong data type passed to
le32_to_cpu()

+ Phillip tested fixed v2 version and it worked well for him. I guess, Phillip was able to spot weird driver behavior, if this cast is wrong.

With regards,
Pavel Skripkin

#39 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 141 lines · Pavel Skripkin
Quoted 105 lines · Fabio M. De Francesco
Quoted 83 lines · CEST Pavel Skripkin
Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Quoted 6 lines

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Hi Pavel,

I (wrongly?) assumed from the prototype of usb_read32() that u32 *data is in native endianness. So, I didn't see the necessity of using _le32 tmp and then convert that tmp with le32_to_cpu().

I simply thought that data could be passed to usbctrl_vendorreq as it-is.

Quoted 1 line

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

Now that you explained that "Data from chip comes in little-endian", obviously I must agree with you that the code needs tmp and that tmp must be swapped by le32_to_cpu(), ahead of assigning it to *data.

Quoted 7 lines

Just a curiosity... Since I was not able to see that *data is returned in little endian, can you please point me where in the code you found out that it is? There must be some place in the code that I'm unable to find and see that *data is LE.

Thanks in advance,

Fabio

Hi, Fabio!

previous usb_read16() realization, which is 100% right:

static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)

{
	u8 requesttype;
	u16 wvalue;
	u16 len;
	__le32 data;

	requesttype = 0x01;/* read_in */
	wvalue = (u16)(addr & 0x0000ffff);
	len = 2;
	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

	return (u16)(le32_to_cpu(data) & 0xffff);
}

Bases on this code, I think, it's oblivious, that data comes in little-endian. That's why I leaved temp variable for casting le32 to cpu's endianess.

I could just read into u{16,32} * and then make smth like

Quoted 8 lines

*data = le32_to_cpu(*data)

but static analysis tools will complain about wrong data type passed to
le32_to_cpu()

+ Phillip tested fixed v2 version and it worked well for him. I guess, Phillip was able to spot weird driver behavior, if this cast is wrong.

		^^^^^&

I am wrong with this statement, I guess. Most likely, Phillip is testing on smth like x64 and this arch is le, so...

With regards,
Pavel Skripkin

#40 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 8 lines · CEST Pavel Skripkin
Quoted 7 lines · Pavel Skripkin

On 8/24/21 11:38 AM, Fabio M. De Francesco wrote:

Hi, Fabio!

previous usb_read16() realization, which is 100% right:

Quoted 6 lines
Quoted 6 lines

static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)

{
	u8 requesttype;
	u16 wvalue;
	u16 len;
	__le32 data;

Ah, it was in plain sight! How didn't I notice it? :(

Quoted 6 lines
Quoted 6 lines
	requesttype = 0x01;/* read_in */
	wvalue = (u16)(addr & 0x0000ffff);
	len = 2;
	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
Quoted 7 lines
Quoted 7 lines
	return (u16)(le32_to_cpu(data) & 0xffff);
}

Bases on this code, I think, it's oblivious, that data comes in little-endian. That's why I leaved temp variable for casting le32 to cpu's endianess.

Yes you did well (if we trust the old code :)), anyway I guess it was correct because I've just seen that data is __le32 also in other Realtek drivers.

Quoted 7 lines
Quoted 7 lines

I could just read into u{16,32} * and then make smth like

*data = le32_to_cpu(*data)

but static analysis tools will complain about wrong data type passed to
le32_to_cpu()

Obviously the (not broken) tools should catch that and complain.

Quoted 11 lines
Quoted 3 lines

+ Phillip tested fixed v2 version and it worked well for him. I guess, Phillip was able to spot weird driver behavior, if this cast is wrong.

		^^^^^&

I am wrong with this statement, I guess. Most likely, Phillip is testing on smth like x64 and this arch is le, so...

With regards,
Pavel Skripkin

Thanks,

Fabio

#104 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 58 lines · CEST Pavel Skripkin
Quoted 49 lines · Dan Carpenter
Quoted 12 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 173

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +3 -1
 
 	requesttype = 0x01;/* read_in */
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);

Add a return here. Try to keep the success path and the failure path as separate as possible. Try to keep the success path indented at one tab so the code looks like this:

	success();
	success();
	if (fail)
		handle_failure();
	success();
	success();

Try to deal with exceptions as quickly as possible so that the reader has less to remember.

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 175

Quoted 2 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +2 -0
+	} else {
+		/* Noone cares about positive return value */

Ugh... That's unfortunate. We should actually care. The usbctrl_vendorreq() has an information leak where it copies len (4) bytes of data even if usb_control_msg() is not able to read len bytes.

The best fix would be to remove the information leak and make usbctrl_vendorreq() return zero on success. In other words something like:

Quoted 7 lines
	status = usb_control_msg();
	if (status < 0)
		return status;
	if (status != len)
		return -EIO;
	status = 0;
Quoted 2 lines

I see, thank you for reviewing, will fix in v3! I fully forgot, that usb_control_msg() can receive only part of the message :)

With the use of the new API I think that you don't have anymore partial messages. usb_control_msg() returns the number of bytes transferred, while usb_control_msg_recv/send return only 0 if successful otherwise a negative error number.

Regards,

Fabio

Quoted 3 lines

With regards,
Pavel Skripkin

#42 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 151 lines · Pavel Skripkin
Quoted 109 lines · Fabio M. De Francesco
Quoted 83 lines · CEST Pavel Skripkin
Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
drivers/staging/r8188eu/hal/usb_ops_linux.c +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 181

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Quoted 8 lines

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Hi Pavel,

I (wrongly?) assumed from the prototype of usb_read32() that u32 *data is in native endianness. So, I didn't see the necessity of using _le32 tmp and then convert that tmp with le32_to_cpu().

I simply thought that data could be passed to usbctrl_vendorreq as it-is.

Quoted 3 lines

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

Now that you explained that "Data from chip comes in little-endian", obviously I must agree with you that the code needs tmp and that tmp must be swapped by le32_to_cpu(), ahead of assigning it to *data.

Quoted 7 lines

Just a curiosity... Since I was not able to see that *data is returned in little endian, can you please point me where in the code you found out that it is? There must be some place in the code that I'm unable to find and see that *data is LE.

Thanks in advance,

Fabio

Hi, Fabio!

previous usb_read16() realization, which is 100% right:

static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)

{
        u8 requesttype;
        u16 wvalue;
        u16 len;
        __le32 data;

        requesttype = 0x01;/* read_in */
        wvalue = (u16)(addr & 0x0000ffff);
        len = 2;
        usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

        return (u16)(le32_to_cpu(data) & 0xffff);
}

Bases on this code, I think, it's oblivious, that data comes in little-endian. That's why I leaved temp variable for casting le32 to cpu's endianess.

I could just read into u{16,32} * and then make smth like

*data = le32_to_cpu(*data)

but static analysis tools will complain about wrong data type passed to
le32_to_cpu()

Quoted 8 lines

+ Phillip tested fixed v2 version and it worked well for him. I guess, Phillip was able to spot weird driver behavior, if this cast is wrong.

With regards,
Pavel Skripkin

In my mind we can't necessarily assume we are running on a little endian CPU, even if we probably are for practical purposes. That's why my fix looked how it did, but I'm happy to be corrected :-) Also, I can see Dan has looked at the code with suggestions as well. I know you have published v3 - sorry, not had time to review/test it yet.

Regards,
Phil

#41 lore raw

Re: [PATCH RFC v2 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 157 lines · Pavel Skripkin
Quoted 145 lines · Pavel Skripkin
Quoted 109 lines · Fabio M. De Francesco
Quoted 83 lines · CEST Pavel Skripkin
Quoted 75 lines · Fabio M. De Francesco
Quoted 35 lines · CEST Phillip Potter
Quoted 21 lines · Pavel Skripkin
(quoted diff) +8 -3
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
        u8 requesttype;
        u16 wvalue;
        u16 len;
-       __le32 data;
+       int res;
+       __le32 tmp;
+
+       if (WARN_ON(unlikely(!data)))
+               return -EINVAL;
 
        requesttype = 0x01;/* read_in */
 
        wvalue = (u16)(addr & 0x0000ffff);
        len = 4;
 
-       usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+       if (res < 0) {

Review

Quoted 10 lines
(quoted diff) +7 -1
+               dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+       } else {
+               /* Noone cares about positive return value */
+               *data = le32_to_cpu(tmp);
+               res = 0;
+       }
 
-       return le32_to_cpu(data);
+       return res;
 }

Dear Pavel,

Quoted 6 lines

OK, found the issue with decoded stack trace after reviewing this usb_read32 function. Your line:
res = usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

should read:
res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);

Dear Philip,

No, it should read:

res = usbctrl_vendorreq(pintfhdl, wvalue, data, len, requesttype);

I suspect that Pavel didn't notice he was reusing a line of the old code wth no due changes.

Quoted 15 lines

With this change, the driver runs fine with no crashes/oopses. I will explain the issue but you can probably see already, so I hope I'm not coming across as patronising, just trying to be helpful :-)

Essentially, you are taking the address of the data function parameter on this line with &data, a pointer to u32, which is giving you a pointer to a pointer to u32 (u32 **) for this function parameter variable. When passed to usbctrl_vendorreq, it is being passed to memcpy inside this function as a void *, meaning that memcpy subsequently overwrites the value of the memory address inside data to point to a different location, which is problem when it is later deferenced at:
*data = le32_to_cpu(tmp);
causing the OOPS

Quoted 7 lines

Also, as written, you can probably see that tmp is uninitialised. This looks like a typo, so guessing this wasn't your intention. Anyhow, with that small change, usbctrl_vendorreq reads into tmp, which is then passed to le32_to_cpu whose return value is stored via the deferenced data ptr (which now has its original address within and not inadvertently modified). Hope this helps, and I'd be happy to Ack the series if you want to resend this patch. Many thanks.

Quoted 6 lines

I think that another typo is having 'tmp', because that variable is unnecessary and "*data = le32_to_cpu(tmp);" is wrong too.

Now I also see that also usb_read16() is wrong, while usb_read8() (the one that I had read yesterday) is the only correct function of the three usb_read*().

Quoted 8 lines

Hi, guys!

Sorry for breaking your system, Phillip. This code was part of "last minute" changes and yes, it's broken :)

I get what Phillip said, because I _should_ read into tmp variable instead of directly to data, but I don't get Fabio's idea, sorry.

Hi Pavel,

I (wrongly?) assumed from the prototype of usb_read32() that u32 *data is in native endianness. So, I didn't see the necessity of using _le32 tmp and then convert that tmp with le32_to_cpu().

I simply thought that data could be passed to usbctrl_vendorreq as it-is.

Quoted 3 lines

Data from chip comes in little-endian, so we _should_ convert it to cpu's endian. Temp variable is needed to make smatch and all other static anylis tools happy about this code.

Now that you explained that "Data from chip comes in little-endian", obviously I must agree with you that the code needs tmp and that tmp must be swapped by le32_to_cpu(), ahead of assigning it to *data.

Quoted 7 lines

Just a curiosity... Since I was not able to see that *data is returned in little endian, can you please point me where in the code you found out that it is? There must be some place in the code that I'm unable to find and see that *data is LE.

Thanks in advance,

Fabio

Hi, Fabio!

previous usb_read16() realization, which is 100% right:

static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)

{
      u8 requesttype;
      u16 wvalue;
      u16 len;
      __le32 data;

      requesttype = 0x01;/* read_in */
      wvalue = (u16)(addr & 0x0000ffff);
      len = 2;
      usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);

      return (u16)(le32_to_cpu(data) & 0xffff);
}

Bases on this code, I think, it's oblivious, that data comes in little-endian. That's why I leaved temp variable for casting le32 to cpu's endianess.

I could just read into u{16,32} * and then make smth like

Quoted 8 lines

*data = le32_to_cpu(*data)

but static analysis tools will complain about wrong data type passed to
le32_to_cpu()

+ Phillip tested fixed v2 version and it worked well for him. I guess, Phillip was able to spot weird driver behavior, if this cast is wrong.

                ^^^^^&
Quoted 8 lines

I am wrong with this statement, I guess. Most likely, Phillip is testing on smth like x64 and this arch is le, so...

With regards,
Pavel Skripkin

Dear Pavel,

You're correct in your assumption, my testing environment is an little-endian x64 QEMU VM with USB passthrough for the wireless adapter. I prefer to test this way so that driver crashes don't bring down the whole machine :-)

Regards,
Phil

#72 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Pavel Skripkin
Quoted 25 lines · CEST Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

[...]

drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data) · line 146

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 
 	requesttype = 0x01;/* read_in */
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 2;
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 16 bytes: %d\n", res);
+		return res;
+	} else if (res != len) {

Dear Pavel,

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read16 () will always return -EIO even if usbctrl_vendorreq () succeeds.

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data) · line 155

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev),
+			"Failed to read 16 bytes, could read only %d bytes\n", res);
+		return -EIO;
+	}
 
-	return (u16)(le32_to_cpu(data) & 0xffff);
+	*data = le32_to_cpu(tmp) & 0xffff;
+
+	return 0;
 }

[...]

Regards,

Fabio

#88 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin
Quoted 27 lines · CEST Pavel Skripkin

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

[...]

drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;
 
 	requesttype = 0x01;/* read_in */

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 177

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 4;
 
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 32 bytes: %d\n", res);
+		return res;
+	} else if (res != len) {

Dear Pavel,

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read32() will always return -EIO even if usbctrl_vendorreq () succeeds.

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 187

Quoted 13 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +7 -1
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev),
+			"Failed to read 32 bytes, could read only %d bytes\n", res);
+		return -EIO;
+	}
+
+	*data = le32_to_cpu(tmp);
 
-	return le32_to_cpu(data);
+	return 0;
 }
 
[...]

Regards,

Fabio

#73 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Fabio M. De Francesco
Quoted 39 lines · Fabio M. De Francesco
Quoted 25 lines · CEST Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

[...]

drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read8(struct intf_hdl *pintfhdl, u32 addr, u8 *data) · line 146

Quoted 10 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 
 	requesttype = 0x01;/* read_in */
 	wvalue = (u16)(addr & 0x0000ffff);
 	len = 2;
-	usbctrl_vendorreq(pintfhdl, wvalue, &data, len, requesttype);
+	res = usbctrl_vendorreq(pintfhdl, wvalue, &tmp, len, requesttype);
+	if (res < 0) {
+		dev_err(dvobj_to_dev(pintfhdl->pintf_dev), "Failed to read 16 bytes: %d\n", res);
+		return res;
+	} else if (res != len) {

Dear Pavel,

Quoted 4 lines

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read16 () will always return -EIO even if usbctrl_vendorreq () succeeds.

Yep, thank you, but it depends on which series will go in first :)

There is a chance, that you will need to clean up this part, if mine will be merged before yours

With regards,
Pavel Skripkin

#74 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 8 lines · CEST Pavel Skripkin
Quoted 6 lines · Fabio M. De Francesco

Dear Pavel,

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read16 () will always return -EIO even if usbctrl_vendorreq () succeeds.

Quoted 5 lines

Yep, thank you, but it depends on which series will go in first :)

There is a chance, that you will need to clean up this part, if mine will be merged before yours

Ha-ha ... I know that beautiful rule: whoever breaks must fix! However there should be another rule which says that the old (me) takes precedence over the young (you) :-)

Seriously, thank you so much for your help and the "Reviewed by" tag on my work.

Regards,

Fabio

Quoted 3 lines

With regards,
Pavel Skripkin

#75 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 9 lines · Fabio M. De Francesco
Quoted 8 lines · CEST Pavel Skripkin
Quoted 6 lines · Fabio M. De Francesco

Dear Pavel,

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read16 () will always return -EIO even if usbctrl_vendorreq () succeeds.

Quoted 9 lines
Quoted 4 lines

Yep, thank you, but it depends on which series will go in first :)

There is a chance, that you will need to clean up this part, if mine will be merged before yours

Ha-ha ... I know that beautiful rule: whoever breaks must fix! However there should be another rule which says that the old (me) takes precedence over the young (you) :-)

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants, because they are naturally independent :)

We only can say smth like "this one depends on this one" as reply to patch to inform Greg about the situation.

Quoted 3 lines

Seriously, thank you so much for your help and the "Reviewed by" tag on my work.

You too :) We are doing same job here for the good of community and kernel itself

With regards,
Pavel Skripkin

#76 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 2 lines · Pavel Skripkin

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants

Patches are always taken in first come first serve.

regards,
dan carpenter

Acked-by on the v3 series
#99 lore raw
In reply to Pavel Skripkin
Quoted 36 lines · CEST Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

To avoid this type of bugs, I've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

v2 -> v3:
1. Fixed OOPS in usb_read32(), caused by writing to u32 **
2. Fixed style in rtw_read32, rtw_read16 and rtw_read8 (Suggested by Dan)
3. Added error hanling when usb_control_msg() returns ret != len
NOTE: Dan suggested to add this to usbctrl_vendorreq(), but there is pending series, which will get rid of usb_control_msg(), so (res != len) check can be removed, when Fabio's series will go in
4. Removed RFC tag

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Quoted 1 line

Phillip has tested fixed v2 version, AFAIU

I had already acked your series when it was an RFC but I guess the tag gets lost now that you have submitted the "real" patches.

As said, I like the purpose and the overall design. Furthermore, I have compiled and linked the whole series (make C=2 -j8 drivers/staging/r8188eu W=1) and I can confirm it does not introduce any errors and/or warnings.

Anyway I couldn't test the module, so (for all six patches)...

Thanks,

Fabio

Quoted 44 lines

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  62 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1143 insertions(+), 389 deletions(-)
Signature · 1 line
2.32.0
#77 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Dan Carpenter
Quoted 6 lines · Dan Carpenter
Quoted 2 lines · Pavel Skripkin

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants

Patches are always taken in first come first serve.

Ok, but if pending patch needs new version, then it will be taken at the end?

Here is the situation we have:

I have the patch series based on old function behavior, it was posted first

Then Fabio posted refactoring of the function and it changes return values.

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

With regards,
Pavel Skripkin

#78 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 11 lines · Pavel Skripkin
Quoted 6 lines · Dan Carpenter
Quoted 2 lines · Pavel Skripkin

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants

Patches are always taken in first come first serve.

Ok, but if pending patch needs new version, then it will be taken at the end?

Versions don't matter. No one is tracking any of that.

A patch arrives. It is either applied or rejected. First come first serve.

Quoted 6 lines

Here is the situation we have:

I have the patch series based on old function behavior, it was posted first

Quoted 7 lines

Then Fabio posted refactoring of the function and it changes return values.

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Also don't write patches which lead to merge order breaking the code silently. That makes it difficult for stable as well. For example, don't do this:

-void frob(int a, int b);
+void frob(int b, int a);

In that case, you would change the name of the function so that the build would break when people mix old and new code.

regards,
dan carpenter

#79 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 10 lines · Dan Carpenter
Quoted 9 lines · Pavel Skripkin
Quoted 6 lines · Dan Carpenter
Quoted 2 lines · Pavel Skripkin

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants

Patches are always taken in first come first serve.

Quoted 8 lines
Quoted 2 lines

Ok, but if pending patch needs new version, then it will be taken at the end?

Versions don't matter. No one is tracking any of that.

A patch arrives. It is either applied or rejected. First come first serve.

Ok, big thanks for explanation

Quoted 24 lines
Quoted 6 lines

Here is the situation we have:

I have the patch series based on old function behavior, it was posted first

Quoted 7 lines

Then Fabio posted refactoring of the function and it changes return values.

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Also don't write patches which lead to merge order breaking the code silently. That makes it difficult for stable as well. For example, don't do this:

(quoted diff) +1 -1
-void frob(int a, int b);
+void frob(int b, int a);
Quoted 3 lines

In that case, you would change the name of the function so that the build would break when people mix old and new code.

Understandable, thank you :)

With regards,
Pavel Skripkin

#84 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Pavel Skripkin
Quoted 28 lines · CEST Pavel Skripkin
Quoted 11 lines · Fabio M. De Francesco
Quoted 10 lines · CEST Pavel Skripkin
Quoted 6 lines · Fabio M. De Francesco

Dear Pavel,

Please note that if and when my patch "Use usb_control_msg_recv / send () in usbctrl_vendorreq ()" will be merged, "if (res! = len)" will always evaluate 'true' and usb_read16 () will always return -EIO even if usbctrl_vendorreq () succeeds.

Yep, thank you, but it depends on which series will go in first :)

Quoted 8 lines
Quoted 3 lines

There is a chance, that you will need to clean up this part, if mine will be merged before yours

Ha-ha ... I know that beautiful rule: whoever breaks must fix! However there should be another rule which says that the old (me) takes precedence over the young (you) :-)

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants, because they are naturally independent :)

We only can say smth like "this one depends on this one" as reply to patch to inform Greg about the situation.

Quoted 7 lines
Quoted 3 lines

Seriously, thank you so much for your help and the "Reviewed by" tag on my work.

You too :) We are doing same job here for the good of community and kernel itself

Pavel, Dan,

Did you really take my "old" vs. "young" precedence rule seriously?

I was just kidding, ahead of thanking Pavel for his "Reviewed-by" tag to my patch.

That statement deserved no comment. I thought it was clear it was just a joke :)

Thanks,

Fabio

Quoted 5 lines

With regards,
Pavel Skripkin

#80 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Dan Carpenter
Quoted 28 lines · CEST Dan Carpenter
Quoted 11 lines · Pavel Skripkin
Quoted 6 lines · Dan Carpenter
Quoted 2 lines · Pavel Skripkin

The main problem, that no one knows who is the "old". Greg can take patches in any order he wants

Patches are always taken in first come first serve.

OK, but if pending patch needs new version, then it will be taken at the end?

Versions don't matter. No one is tracking any of that.

A patch arrives. It is either applied or rejected. First come first serve.

Quoted 10 lines

Here is the situation we have:

I have the patch series based on old function behavior, it was posted first

Then Fabio posted refactoring of the function and it changes return values.

Quoted 6 lines
Quoted 3 lines

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Sorry Dan, I disagree. It's not a bug. No one intend to break the code. How could anyone know that someone else is working simultaneously on some code that is not compatible with the work of the other developer?

Pavel and I worked simultaneously on code based on the current Greg's tree.

We incidentally got to know that mine breaks his.

I suppose that Greg will take Pavel's work first, because it was submitted few hours before mine and then will ask me to take into account Pavel's patches, rebase, fix and resend mine.

Each series is self contained and does not introduce bugs to the current tree. The bugs will arise when Greg will have applied one of the two series as usually in a FIFO order.

There's no practical means to know who is working to what just by reading all the messages of the lists. Who reads all the messages before deciding to work on something? This issue will be solved a way or the other, I really don't think it is a big problem, it's unavoidable when a lot of people work on the same driver or subsystem.

Regards,

Fabio

Quoted 14 lines

Also don't write patches which lead to merge order breaking the code silently. That makes it difficult for stable as well. For example, don't do this:

(quoted diff) +1 -1
-void frob(int a, int b);
+void frob(int b, int a);

In that case, you would change the name of the function so that the build would break when people mix old and new code.

regards,
dan carpenter

#81 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

Quoted 27 lines · CEST Fabio M. De Francesco
Quoted 2 lines · CEST Dan Carpenter

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Sorry Dan, I disagree. It's not a bug. No one intend to break the code. How could anyone know that someone else is working simultaneously on some code that is not compatible with the work of the other developer?

Pavel and I worked simultaneously on code based on the current Greg's tree.

We incidentally got to know that mine breaks his.

I suppose that Greg will take Pavel's work first, because it was submitted few hours before mine and then will ask me to take into account Pavel's patches, rebase, fix and resend mine.

Each series is self contained and does not introduce bugs to the current tree. The bugs will arise when Greg will have applied one of the two series as usually in a FIFO order.

There's no practical means to know who is working to what just by reading all the messages of the lists. Who reads all the messages before deciding to work on something? This issue will be solved a way or the other, I really don't think it is a big problem, it's unavoidable when a lot of people work on the same driver or subsystem.

Quoted 3 lines

Regards,

Fabio

For sake of completeness I want to say that when Pavel had only submitted RFC v2 my code didn't break his. It was only with his v3 that the bug went out. But v3 was submitted just few hours before mine.

Fabio

#82 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Fabio M. De Francesco
Quoted 6 lines · Fabio M. De Francesco
Quoted 5 lines · CEST Dan Carpenter
Quoted 3 lines · Pavel Skripkin

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

Quoted 6 lines
Quoted 2 lines

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Sorry Dan, I disagree. It's not a bug. No one intend to break the code. How could anyone know that someone else is working simultaneously on some code that is not compatible with the work of the other developer?

Okay, I haven't been following the discussion closely. If these patches introduce a known bug, then I am going to be cross.

I'm really stressed out right now. If you at all suspect that your patches are going to introduce bugs then just go back and say "Sorry, don't take this one, the way it conflicts with Pavels ends up introducing a bug. I'll resend after Pavel's patches are applied."

regards,
dan carpenter

#51 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin
Thank you for the patch! Yet something to improve:

Hi Pavel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: arm-buildonly-randconfig-r001-20210825 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ea08c4cd1c0869ec5024a8bb3f5cdf06ab03ae83)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install binutils-arm-linux-gnueabi
# https://github.com/0day-ci/linux/commit/d4e4bbed4e59df37967086f60fe92cb1b4504d37
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756 git checkout d4e4bbed4e59df37967086f60fe92cb1b4504d37
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/staging/r8188eu/

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

>> drivers/staging/r8188eu/hal/usb_halinit.c:2022:3: error: expected expression
                   u8 tmp;
                   ^

1 error generated.

Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for QCOM_SCM
Depends on (ARM || ARM64) && HAVE_ARM_SMCCC
Selected by
- ARM_QCOM_SPM_CPUIDLE && CPU_IDLE && (ARM || ARM64) && (ARCH_QCOM || COMPILE_TEST && !ARM64 && MMU

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

1450
1451 static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
1452 {
1453 struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
1454 struct dm_priv *pdmpriv = &haldata->dmpriv;
1455 struct odm_dm_struct *podmpriv = &haldata->odmpriv;
1456 int error;
1457 u8 tmp;
1458
1459 switch (variable) {
1460 case HW_VAR_MEDIA_STATUS:
1461 {
1462 u8 val8;
1463
1464 error = rtw_read8(Adapter, MSR, &val8);
1465 if (error)
1466 return;
1467
1468 val8 &= 0x0c;
1469 val8 |= *((u8 *)val);
1470 rtw_write8(Adapter, MSR, val8);
1471 }
1472 break;
1473 case HW_VAR_MEDIA_STATUS1:
1474 {
1475 u8 val8;
1476
1477 error = rtw_read8(Adapter, MSR, &val8);
1478 if (error)
1479 return;
1480
1481 val8 &= 0x03;
1482 val8 |= *((u8 *)val) << 2;
1483 rtw_write8(Adapter, MSR, val8);
1484 }
1485 break;
1486 case HW_VAR_SET_OPMODE:
1487 hw_var_set_opmode(Adapter, variable, val);
1488 break;
1489 case HW_VAR_MAC_ADDR:
1490 hw_var_set_macaddr(Adapter, variable, val);
1491 break;
1492 case HW_VAR_BSSID:
1493 hw_var_set_bssid(Adapter, variable, val);
1494 break;
1495 case HW_VAR_BASIC_RATE:
1496 {
1497 u16 BrateCfg = 0;
1498 u8 RateIndex = 0;
1499

  1500				/*  2007.01.16, by Emily */
  1501				/*  Select RRSR (in Legacy-OFDM and CCK) */
  1502				/*  For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */
  1503				/*  We do not use other rates. */
  1504				HalSetBrateCfg(Adapter, val, &BrateCfg);
  1505				DBG_88E("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg);
  1506	
  1507				/* 2011.03.30 add by Luke Lee */
  1508				/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
  1509				/* because CCK 2M has poor TXEVM */
  1510				/* CCK 5.5M & 11M ACK should be enabled for better performance */
  1511	
  1512				BrateCfg = (BrateCfg | 0xd) & 0x15d;
  1513				haldata->BasicRateSet = BrateCfg;
  1514	
  1515				BrateCfg |= 0x01; /*  default enable 1M ACK rate */
  1516				/*  Set RRSR rate table. */
  1517				rtw_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
  1518				rtw_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff);
  1519	
  1520				error = rtw_read8(Adapter, REG_RRSR + 2, &tmp);
  1521				if (error)
  1522					return;
  1523	
  1524				rtw_write8(Adapter, REG_RRSR + 2, tmp & 0xf0);
  1525	
  1526				/*  Set RTS initial rate */
  1527				while (BrateCfg > 0x1) {
  1528					BrateCfg = (BrateCfg >> 1);
  1529					RateIndex++;
  1530				}
  1531				/*  Ziv - Check */
  1532				rtw_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
  1533			}
  1534			break;
  1535		case HW_VAR_TXPAUSE:
  1536			rtw_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
  1537			break;
  1538		case HW_VAR_BCN_FUNC:
  1539			hw_var_set_bcn_func(Adapter, variable, val);
  1540			break;
  1541		case HW_VAR_CORRECT_TSF:
  1542			{
  1543				u64	tsf;
  1544				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1545				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1546	
  1547				tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue,
  1548								  pmlmeinfo->bcn_interval * 1024) - 1024; /* us */
  1549	
  1550				if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
  1551					StopTxBeacon(Adapter);
  1552	
  1553				/* disable related TSF function */
  1554				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1555				if (error)
  1556					return;
  1557	
  1558				rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(3)));
  1559	
  1560				rtw_write32(Adapter, REG_TSFTR, tsf);
  1561				rtw_write32(Adapter, REG_TSFTR + 4, tsf >> 32);
  1562	
  1563				/* enable related TSF function */
  1564				error =  rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1565				if (error)
  1566					return;
  1567	
  1568				rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(3));
  1569	
  1570				if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
  1571					ResumeTxBeacon(Adapter);
  1572			}
  1573			break;
  1574		case HW_VAR_CHECK_BSSID:
  1575			if (*((u8 *)val)) {
  1576				rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1577			} else {
  1578				u32 val32;
  1579	
  1580				val32 = rtw_read32(Adapter, REG_RCR);
  1581	
  1582				val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1583	
  1584				rtw_write32(Adapter, REG_RCR, val32);
  1585			}
  1586			break;
  1587		case HW_VAR_MLME_DISCONNECT:
  1588			/* Set RCR to not to receive data frame when NO LINK state */
  1589			/* reject all data frames */
  1590			rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1591	
  1592			/* reset TSF */
  1593			rtw_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
  1594	
  1595			/* disable update TSF */
  1596			error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1597			if (error)
  1598				return;
  1599	
  1600			rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(4));
  1601			break;
  1602		case HW_VAR_MLME_SITESURVEY:
  1603			if (*((u8 *)val)) { /* under sitesurvey */
  1604				/* config RCR to receive different BSSID & not to receive data frame */
  1605				u32 v = rtw_read32(Adapter, REG_RCR);
  1606	
  1607				v &= ~(RCR_CBSSID_BCN);
  1608				rtw_write32(Adapter, REG_RCR, v);
  1609				/* reject all data frame */
  1610				rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1611	
  1612				/* disable update TSF */
  1613				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1614				if (error)
  1615					return;
  1616				rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(4));
  1617			} else { /* sitesurvey done */
  1618				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1619				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1620	
  1621				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1622				if (error)
  1623					return;
  1624	
  1625				if ((is_client_associated_to_ap(Adapter)) ||
  1626				    ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
  1627					/* enable to rx data frame */
  1628					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1629	
  1630					/* enable update TSF */
  1631					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1632				} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  1633					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1634					/* enable update TSF */
  1635					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1636				}
  1637	
  1638				if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  1639					rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
  1640				} else {
  1641					if (Adapter->in_cta_test) {
  1642						u32 v = rtw_read32(Adapter, REG_RCR);
  1643						v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
  1644						rtw_write32(Adapter, REG_RCR, v);
  1645					} else {
  1646						rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
  1647					}
  1648				}
  1649			}
  1650			break;
  1651		case HW_VAR_MLME_JOIN:
  1652			{
  1653				u8 RetryLimit = 0x30;
  1654				u8 type = *((u8 *)val);
  1655				u8 tmp;
  1656				struct mlme_priv	*pmlmepriv = &Adapter->mlmepriv;
  1657	
  1658				if (type == 0) { /*  prepare to join */
  1659					/* enable to rx data frame.Accept all data frame */
  1660					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1661	
  1662					if (Adapter->in_cta_test) {
  1663						u32 v = rtw_read32(Adapter, REG_RCR);
  1664						v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
  1665						rtw_write32(Adapter, REG_RCR, v);
  1666					} else {
  1667						rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1668					}
  1669	
  1670					if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
  1671						RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48;
  1672					else /*  Ad-hoc Mode */
  1673						RetryLimit = 0x7;
  1674				} else if (type == 1) {
  1675					/* joinbss_event call back when join res < 0 */
  1676					rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1677				} else if (type == 2) {
  1678					/* sta add event call back */
  1679					/* enable update TSF */
  1680					error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1681					if (error)
  1682						return;
  1683	
  1684					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1685	
  1686					if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
  1687						RetryLimit = 0x7;
  1688				}
  1689				rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
  1690			}
  1691			break;
  1692		case HW_VAR_BEACON_INTERVAL:
  1693			rtw_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
  1694			break;
  1695		case HW_VAR_SLOT_TIME:
  1696			{
  1697				u8 u1bAIFS, aSifsTime;
  1698				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1699				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1700	
  1701				rtw_write8(Adapter, REG_SLOT, val[0]);
  1702	
  1703				if (pmlmeinfo->WMM_enable == 0) {
  1704					if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
  1705						aSifsTime = 10;
  1706					else
  1707						aSifsTime = 16;
  1708	
  1709					u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
  1710	
  1711					/*  <Roger_EXP> Temporary removed, 2008.06.20. */
  1712					rtw_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
  1713					rtw_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
  1714					rtw_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
  1715					rtw_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
  1716				}
  1717			}
  1718			break;
  1719		case HW_VAR_RESP_SIFS:
  1720			/* RESP_SIFS for CCK */
  1721			rtw_write8(Adapter, REG_R2T_SIFS, val[0]); /*  SIFS_T2T_CCK (0x08) */
  1722			rtw_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */
  1723			/* RESP_SIFS for OFDM */
  1724			rtw_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
  1725			rtw_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
  1726			break;
  1727		case HW_VAR_ACK_PREAMBLE:
  1728			{
  1729				u8 regTmp;
  1730				u8 bShortPreamble = *((bool *)val);
  1731				/*  Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
  1732				regTmp = (haldata->nCur40MhzPrimeSC) << 5;
  1733				if (bShortPreamble)
  1734					regTmp |= 0x80;
  1735	
  1736				rtw_write8(Adapter, REG_RRSR + 2, regTmp);
  1737			}
  1738			break;
  1739		case HW_VAR_SEC_CFG:
  1740			rtw_write8(Adapter, REG_SECCFG, *((u8 *)val));
  1741			break;
  1742		case HW_VAR_DM_FLAG:
  1743			podmpriv->SupportAbility = *((u8 *)val);
  1744			break;
  1745		case HW_VAR_DM_FUNC_OP:
  1746			if (val[0])
  1747				podmpriv->BK_SupportAbility = podmpriv->SupportAbility;
  1748			else
  1749				podmpriv->SupportAbility = podmpriv->BK_SupportAbility;
  1750			break;
  1751		case HW_VAR_DM_FUNC_SET:
  1752			if (*((u32 *)val) == DYNAMIC_ALL_FUNC_ENABLE) {
  1753				pdmpriv->DMFlag = pdmpriv->InitDMFlag;
  1754				podmpriv->SupportAbility =	pdmpriv->InitODMFlag;
  1755			} else {
  1756				podmpriv->SupportAbility |= *((u32 *)val);
  1757			}
  1758			break;
  1759		case HW_VAR_DM_FUNC_CLR:
  1760			podmpriv->SupportAbility &= *((u32 *)val);
  1761			break;
  1762		case HW_VAR_CAM_EMPTY_ENTRY:
  1763			{
  1764				u8 ucIndex = *((u8 *)val);
  1765				u8 i;
  1766				u32 ulCommand = 0;
  1767				u32 ulContent = 0;
  1768				u32 ulEncAlgo = CAM_AES;
  1769	
  1770				for (i = 0; i < CAM_CONTENT_COUNT; i++) {
  1771					/*  filled id in CAM config 2 byte */
  1772					if (i == 0)
  1773						ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2);
  1774					else
  1775						ulContent = 0;
  1776					/*  polling bit, and No Write enable, and address */
  1777					ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
  1778					ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
  1779					/*  write content 0 is equall to mark invalid */
  1780					rtw_write32(Adapter, WCAMI, ulContent);  /* delay_ms(40); */
  1781					rtw_write32(Adapter, RWCAM, ulCommand);  /* delay_ms(40); */
  1782				}
  1783			}
  1784			break;
  1785		case HW_VAR_CAM_INVALID_ALL:
  1786			rtw_write32(Adapter, RWCAM, BIT(31) | BIT(30));
  1787			break;
  1788		case HW_VAR_CAM_WRITE:
  1789			{
  1790				u32 cmd;
  1791				u32 *cam_val = (u32 *)val;
  1792				rtw_write32(Adapter, WCAMI, cam_val[0]);
  1793	
  1794				cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
  1795				rtw_write32(Adapter, RWCAM, cmd);
  1796			}
  1797			break;
  1798		case HW_VAR_AC_PARAM_VO:
  1799			rtw_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
  1800			break;
  1801		case HW_VAR_AC_PARAM_VI:
  1802			rtw_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
  1803			break;
  1804		case HW_VAR_AC_PARAM_BE:
  1805			haldata->AcParam_BE = ((u32 *)(val))[0];
  1806			rtw_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
  1807			break;
  1808		case HW_VAR_AC_PARAM_BK:
  1809			rtw_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
  1810			break;
  1811		case HW_VAR_ACM_CTRL:
  1812			{
  1813				u8 acm_ctrl = *((u8 *)val);
  1814				u8 AcmCtrl;
  1815	
  1816				error = rtw_read8(Adapter, REG_ACMHWCTRL, &AcmCtrl);
  1817				if (error)
  1818					return;
  1819	
  1820				if (acm_ctrl > 1)
  1821					AcmCtrl = AcmCtrl | 0x1;
  1822	
  1823				if (acm_ctrl & BIT(3))
  1824					AcmCtrl |= AcmHw_VoqEn;
  1825				else
  1826					AcmCtrl &= (~AcmHw_VoqEn);
  1827	
  1828				if (acm_ctrl & BIT(2))
  1829					AcmCtrl |= AcmHw_ViqEn;
  1830				else
  1831					AcmCtrl &= (~AcmHw_ViqEn);
  1832	
  1833				if (acm_ctrl & BIT(1))
  1834					AcmCtrl |= AcmHw_BeqEn;
  1835				else
  1836					AcmCtrl &= (~AcmHw_BeqEn);
  1837	
  1838				DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
  1839				rtw_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
  1840			}
  1841			break;
  1842		case HW_VAR_AMPDU_MIN_SPACE:
  1843			{
  1844				u8 MinSpacingToSet;
  1845				u8 SecMinSpace;
  1846				u8 tmp;
  1847	
  1848				MinSpacingToSet = *((u8 *)val);
  1849				if (MinSpacingToSet <= 7) {
  1850					switch (Adapter->securitypriv.dot11PrivacyAlgrthm) {
  1851					case _NO_PRIVACY_:
  1852					case _AES_:
  1853						SecMinSpace = 0;
  1854						break;
  1855					case _WEP40_:
  1856					case _WEP104_:
  1857					case _TKIP_:
  1858					case _TKIP_WTMIC_:
  1859						SecMinSpace = 6;
  1860						break;
  1861					default:
  1862						SecMinSpace = 7;
  1863						break;
  1864					}
  1865					if (MinSpacingToSet < SecMinSpace)
  1866						MinSpacingToSet = SecMinSpace;
  1867	
  1868					error = rtw_read8(Adapter, REG_AMPDU_MIN_SPACE, &tmp);
  1869					if (error)
  1870						return;
  1871	
  1872					rtw_write8(Adapter, REG_AMPDU_MIN_SPACE, (tmp & 0xf8) |
  1873						  MinSpacingToSet);
  1874				}
  1875			}
  1876			break;
  1877		case HW_VAR_AMPDU_FACTOR:
  1878			{
  1879				u8 RegToSet_Normal[4] = {0x41, 0xa8, 0x72, 0xb9};
  1880				u8 FactorToSet;
  1881				u8 *pRegToSet;
  1882				u8 index = 0;
  1883	
  1884				pRegToSet = RegToSet_Normal; /*  0xb972a841; */
  1885				FactorToSet = *((u8 *)val);
  1886				if (FactorToSet <= 3) {
  1887					FactorToSet = (1 << (FactorToSet + 2));
  1888					if (FactorToSet > 0xf)
  1889						FactorToSet = 0xf;
  1890	
  1891					for (index = 0; index < 4; index++) {
  1892						if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
  1893							pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4);
  1894	
  1895						if ((pRegToSet[index] & 0x0f) > FactorToSet)
  1896							pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet);
  1897	
  1898						rtw_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]);
  1899					}
  1900				}
  1901			}
  1902			break;
  1903		case HW_VAR_RXDMA_AGG_PG_TH:
  1904			{
  1905				u8 threshold = *((u8 *)val);
  1906				if (threshold == 0)
  1907					threshold = haldata->UsbRxAggPageCount;
  1908				rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
  1909			}
  1910			break;
  1911		case HW_VAR_SET_RPWM:
  1912			break;
  1913		case HW_VAR_H2C_FW_PWRMODE:
  1914			{
  1915				u8 psmode = (*(u8 *)val);
  1916	
  1917				/*  Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
  1918				/*  saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
  1919				if ((psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(haldata->VersionID)))
  1920					ODM_RF_Saving(podmpriv, true);
  1921				rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
  1922			}
  1923			break;
  1924		case HW_VAR_H2C_FW_JOINBSSRPT:
  1925			{
  1926				u8 mstatus = (*(u8 *)val);
  1927				rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus);
  1928			}
  1929			break;
  1930	#ifdef CONFIG_88EU_P2P
  1931		case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
  1932			{
  1933				u8 p2p_ps_state = (*(u8 *)val);
  1934				rtl8188e_set_p2p_ps_offload_cmd(Adapter, p2p_ps_state);
  1935			}
  1936			break;
  1937	#endif
  1938		case HW_VAR_INITIAL_GAIN:
  1939			{
  1940				struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
  1941				u32 rx_gain = ((u32 *)(val))[0];
  1942	
  1943				if (rx_gain == 0xff) {/* restore rx gain */
  1944					ODM_Write_DIG(podmpriv, pDigTable->BackupIGValue);
  1945				} else {
  1946					pDigTable->BackupIGValue = pDigTable->CurIGValue;
  1947					ODM_Write_DIG(podmpriv, rx_gain);
  1948				}
  1949			}
  1950			break;
  1951		case HW_VAR_TRIGGER_GPIO_0:
  1952			rtl8192cu_trigger_gpio_0(Adapter);
  1953			break;
  1954		case HW_VAR_RPT_TIMER_SETTING:
  1955			{
  1956				u16 min_rpt_time = (*(u16 *)val);
  1957				ODM_RA_Set_TxRPT_Time(podmpriv, min_rpt_time);
  1958			}
  1959			break;
  1960		case HW_VAR_ANTENNA_DIVERSITY_SELECT:
  1961			{
  1962				u8 Optimum_antenna = (*(u8 *)val);
  1963				u8 Ant;
  1964				/* switch antenna to Optimum_antenna */
  1965				if (haldata->CurAntenna !=  Optimum_antenna) {
  1966					Ant = (Optimum_antenna == 2) ? MAIN_ANT : AUX_ANT;
  1967					ODM_UpdateRxIdleAnt_88E(&haldata->odmpriv, Ant);
  1968	
  1969					haldata->CurAntenna = Optimum_antenna;
  1970				}
  1971			}
  1972			break;
  1973		case HW_VAR_EFUSE_BYTES: /*  To set EFUE total used bytes, added by Roger, 2008.12.22. */
  1974			haldata->EfuseUsedBytes = *((u16 *)val);
  1975			break;
  1976		case HW_VAR_FIFO_CLEARN_UP:
  1977			{
  1978				struct pwrctrl_priv *pwrpriv = &Adapter->pwrctrlpriv;
  1979				u8 trycnt = 100;
  1980	
  1981				/* pause tx */
  1982				rtw_write8(Adapter, REG_TXPAUSE, 0xff);
  1983	
  1984				/* keep sn */
  1985				Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
  1986	
  1987				if (!pwrpriv->bkeepfwalive) {
  1988					/* RX DMA stop */
  1989					rtw_write32(Adapter, REG_RXPKT_NUM, (rtw_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
  1990					do {
  1991						if (!(rtw_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE))
  1992							break;
  1993					} while (trycnt--);
  1994					if (trycnt == 0)
  1995						DBG_88E("Stop RX DMA failed......\n");
  1996	
  1997					/* RQPN Load 0 */
  1998					rtw_write16(Adapter, REG_RQPN_NPQ, 0x0);
  1999					rtw_write32(Adapter, REG_RQPN, 0x80000000);
  2000					mdelay(10);
  2001				}
  2002			}
  2003			break;
  2004		case HW_VAR_CHECK_TXBUF:
  2005			break;
  2006		case HW_VAR_APFM_ON_MAC:
  2007			haldata->bMacPwrCtrlOn = *val;
  2008			DBG_88E("%s: bMacPwrCtrlOn=%d\n", __func__, haldata->bMacPwrCtrlOn);
  2009			break;
  2010		case HW_VAR_TX_RPT_MAX_MACID:
  2011			{
  2012				u8 maxMacid = *val;
  2013				DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1);
  2014				rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);
  2015			}
  2016			break;
  2017		case HW_VAR_H2C_MEDIA_STATUS_RPT:
  2018			rtl8188e_set_FwMediaStatus_cmd(Adapter, (*(__le16 *)val));
  2019			break;
  2020		case HW_VAR_BCN_VALID:
  2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
> 2022			u8 tmp;

2023
2024 error = rtw_read8(Adapter, REG_TDECTRL + 2, &tmp);
2025 if (error)
2026 return;
2027
2028 rtw_write8(Adapter, REG_TDECTRL + 2, tmp | BIT(0));
2029 break;
2030 default:
2031 break;
2032 }
2033

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#83 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Dan Carpenter
Quoted 17 lines · CEST Dan Carpenter
Quoted 6 lines · Fabio M. De Francesco
Quoted 5 lines · CEST Dan Carpenter
Quoted 3 lines · Pavel Skripkin

Both series are pending right now and made on top of staging-next branch. Who needs to rebase? I think, applying these series as-is can broke the driver, since error handling will be broken

Quoted 6 lines
Quoted 2 lines

That's a bug then. The patch should be rejected. You're not allowed to break the code.

Sorry Dan, I disagree. It's not a bug. No one intend to break the code. How could anyone know that someone else is working simultaneously on some code that is not compatible with the work of the other developer?

Okay, I haven't been following the discussion closely. If these patches introduce a known bug, then I am going to be cross.

Quoted 8 lines

I'm really stressed out right now. If you at all suspect that your patches are going to introduce bugs then just go back and say "Sorry, don't take this one, the way it conflicts with Pavel's ends up introducing a bug. I'll resend after Pavel's patches are applied."

regards,
dan carpenter

Dear Dan,

Yours is a nice solution to this problem.

I had thought that I should have waited for Greg to ask to take into account Pavel's series, change some lines of his code (because they are the only users of the new version of the helper function, that is my work - as suggested by Greg himself), rebase and resend, I really think that your idea is better.

I'll do as you suggest ASAP, within the end of the day (now I have to go).

Thanks very much.

Fabio

#52 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to kernel test robot
Quoted 33 lines · kernel test robot

Hi Pavel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: arm-buildonly-randconfig-r001-20210825 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ea08c4cd1c0869ec5024a8bb3f5cdf06ab03ae83)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install 11.1.1
# https://github.com/0day-ci/linux/commit/d4e4bbed4e59df37967086f60fe92cb1b4504d37
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756 git checkout d4e4bbed4e59df37967086f60fe92cb1b4504d37
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/staging/r8188eu/

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

Quoted 1 line
Quoted 1 line

drivers/staging/r8188eu/hal/usb_halinit.c:2022:3: error: expected expression

                    u8 tmp;
                    ^
    1 error generated.
Quoted 7 lines

Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for QCOM_SCM
Depends on (ARM || ARM64) && HAVE_ARM_SMCCC
Selected by
- ARM_QCOM_SPM_CPUIDLE && CPU_IDLE && (ARM || ARM64) && (ARCH_QCOM || COMPILE_TEST && !ARM64 && MMU

We need to fix Kconfig, ok, I will take a look at it later

Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

   2020		case HW_VAR_BCN_VALID:
   2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

Quoted 12 lines
   2023	
   2024			error = rtw_read8(Adapter, REG_TDECTRL + 2, &tmp);
   2025			if (error)
   2026				return;
   2027	
   2028			rtw_write8(Adapter, REG_TDECTRL + 2, tmp | BIT(0));
   2029			break;
   2030		default:
   2031			break;
   2032		}
   2033	

With regards,
Pavel Skripkin

#53 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 42 lines · Pavel Skripkin
Quoted 33 lines · kernel test robot

Hi Pavel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: arm-buildonly-randconfig-r001-20210825 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ea08c4cd1c0869ec5024a8bb3f5cdf06ab03ae83)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install 11.1.1
# https://github.com/0day-ci/linux/commit/d4e4bbed4e59df37967086f60fe92cb1b4504d37
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756 git checkout d4e4bbed4e59df37967086f60fe92cb1b4504d37
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/staging/r8188eu/

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

Quoted 1 line
Quoted 1 line

drivers/staging/r8188eu/hal/usb_halinit.c:2022:3: error: expected expression

                    u8 tmp;
                    ^
    1 error generated.
Quoted 7 lines

Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for QCOM_SCM
Depends on (ARM || ARM64) && HAVE_ARM_SMCCC
Selected by
- ARM_QCOM_SPM_CPUIDLE && CPU_IDLE && (ARM || ARM64) && (ARCH_QCOM || COMPILE_TEST && !ARM64 && MMU

Quoted 2 lines

We need to fix Kconfig, ok, I will take a look at it later

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

   2020		case HW_VAR_BCN_VALID:
   2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

regards,
dan carpenter

#54 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 59 lines · Dan Carpenter
Quoted 42 lines · Pavel Skripkin
Quoted 33 lines · kernel test robot

Hi Pavel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: arm-buildonly-randconfig-r001-20210825 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ea08c4cd1c0869ec5024a8bb3f5cdf06ab03ae83)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install 11.1.1
# https://github.com/0day-ci/linux/commit/d4e4bbed4e59df37967086f60fe92cb1b4504d37
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756 git checkout d4e4bbed4e59df37967086f60fe92cb1b4504d37
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/staging/r8188eu/

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

Quoted 1 line
Quoted 1 line

drivers/staging/r8188eu/hal/usb_halinit.c:2022:3: error: expected expression

                    u8 tmp;
                    ^
    1 error generated.
Quoted 7 lines

Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for QCOM_SCM
Depends on (ARM || ARM64) && HAVE_ARM_SMCCC
Selected by
- ARM_QCOM_SPM_CPUIDLE && CPU_IDLE && (ARM || ARM64) && (ARCH_QCOM || COMPILE_TEST && !ARM64 && MMU

Quoted 2 lines

We need to fix Kconfig, ok, I will take a look at it later

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

   2020		case HW_VAR_BCN_VALID:
   2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Quoted 9 lines

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

AFAIK, at least 2 guys except me in this CC list compiled my series without errors/warnings. Maybe, staging tree is missing some Makefile updates?

I'll resend series this evening anyway, but this is strange....

With regards,
Pavel Skripkin

#55 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 23 lines · Pavel Skripkin
Quoted 13 lines

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

   2020		case HW_VAR_BCN_VALID:
   2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Quoted 9 lines

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

Quoted 5 lines

AFAIK, at least 2 guys except me in this CC list compiled my series without errors/warnings. Maybe, staging tree is missing some Makefile updates?

I'll resend series this evening anyway, but this is strange....

Hm... In my version of GCC the error is:

drivers/staging/r8188eu/hal/usb_halinit.c:1870:3: error: a label can only be part of a statement and a declaration is not a statement

That's a different error from what I was expecting. It's caused by having a declaration directly after a case statement. The warning that I was expecting was from -Wdeclaration-after-statement and it looks like this:

warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]

You really should try investigate why this compiles for you because something is going wrong. It should not build without a warning.

regards,
dan carpenter

#56 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 39 lines · Dan Carpenter
Quoted 23 lines · Pavel Skripkin
Quoted 13 lines

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

   2020		case HW_VAR_BCN_VALID:
   2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Quoted 9 lines

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

Quoted 5 lines

AFAIK, at least 2 guys except me in this CC list compiled my series without errors/warnings. Maybe, staging tree is missing some Makefile updates?

I'll resend series this evening anyway, but this is strange....

Hm... In my version of GCC the error is:

drivers/staging/r8188eu/hal/usb_halinit.c:1870:3: error: a label can only be part of a statement and a declaration is not a statement

That's a different error from what I was expecting. It's caused by having a declaration directly after a case statement. The warning that I was expecting was from -Wdeclaration-after-statement and it looks like this:

Quoted 5 lines

warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]

You really should try investigate why this compiles for you because something is going wrong. It should not build without a warning.

Looks like it's bug in gcc 11.1.1. I've rebuilt this module with gcc 10 (gcc-10 (SUSE Linux) 10.3.1 20210707 [revision 048117e16c77f82598fca9af585500572d46ad73]) and build fails with error described above

My default gcc is

gcc (SUSE Linux) 11.1.1 20210721 [revision
076930b9690ac3564638636f6b13bbb6bc608aea]

Any idea? :)

With regards,
Pavel Skripkin

#57 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 53 lines · Pavel Skripkin
Quoted 39 lines · Dan Carpenter
Quoted 23 lines · Pavel Skripkin
Quoted 13 lines

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

2020 case HW_VAR_BCN_VALID:
2021 /* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */

Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Quoted 9 lines

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

Quoted 5 lines

AFAIK, at least 2 guys except me in this CC list compiled my series without errors/warnings. Maybe, staging tree is missing some Makefile updates?

I'll resend series this evening anyway, but this is strange....

Hm... In my version of GCC the error is:

drivers/staging/r8188eu/hal/usb_halinit.c:1870:3: error: a label can only be part of a statement and a declaration is not a statement

That's a different error from what I was expecting. It's caused by having a declaration directly after a case statement. The warning that I was expecting was from -Wdeclaration-after-statement and it looks like this:

Quoted 5 lines

warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]

You really should try investigate why this compiles for you because something is going wrong. It should not build without a warning.

Looks like it's bug in gcc 11.1.1. I've rebuilt this module with gcc 10 (gcc-10 (SUSE Linux) 10.3.1 20210707 [revision 048117e16c77f82598fca9af585500572d46ad73]) and build fails with error described above

Quoted 7 lines

My default gcc is

gcc (SUSE Linux) 11.1.1 20210721 [revision
076930b9690ac3564638636f6b13bbb6bc608aea]

Any idea? :)

The original report said the build was with clang-14, which is near top of tree and unreleased. It's possible that that build had a bug that hopefully was reverted.

Signature · 2 lines
Thanks,
~Nick Desaulniers
#59 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin
Quoted 10 lines · CEST Pavel Skripkin

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Dear Pavel,

I have to inform you that building patch v3 3/6 with gcc (version 11.1.1 20210721 [revision 076930b9690ac3564638636f6b13bbb6bc608aea] (SUSE Linux)), gives the following warning:

drivers/staging/r8188eu/os_dep/ioctl_linux.c:2258:13: warning: variable ‘error’ set but not used [-Wunused-but-set-variable]

 2258 |         int error;
      |             ^~~~~

I'm sorry, but I guess that for some reason previously I had only built v2 of your patch which had no warnings at all.

Unfortunately, introducing warnings is not allowed.

While we are at this, I can also confirm that GCC 11.1.1 _does_ _not_ emit the warning that has been reported by the kernel test robot.

Regards,

Fabio

#60 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 22 lines · Fabio M. De Francesco
Quoted 10 lines · CEST Pavel Skripkin

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Dear Pavel,

I have to inform you that building patch v3 3/6 with gcc (version 11.1.1 20210721 [revision 076930b9690ac3564638636f6b13bbb6bc608aea] (SUSE Linux)), gives the following warning:

drivers/staging/r8188eu/os_dep/ioctl_linux.c:2258:13: warning: variable ‘error’ set but not used [-Wunused-but-set-variable]

  2258 |         int error;
       |             ^~~~~
Quoted 8 lines

I'm sorry, but I guess that for some reason previously I had only built v2 of your patch which had no warnings at all.

Unfortunately, introducing warnings is not allowed.

While we are at this, I can also confirm that GCC 11.1.1 _does_ _not_ emit the warning that has been reported by the kernel test robot.

Yep, I see, thank you. v4 is on the way... I had a plan to send v4 yesterday, but I've finally received r8188eu device.

I tried to connect it and test and.... driver didn't work :) So, I will try to figure out the problem with driver (or device) and will send v4.

Again, thank you for report :) My default gcc is too polite...

With regards,
Pavel Skripkin

#61 lore raw

RE: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin

From: Pavel Skripkin

Quoted 10 lines

Sent: 24 August 2021 08:27

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 2 lines
drivers/staging/r8188eu/core/rtw_debug.c +2 -0
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);

That is broken.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#62 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 12 lines · On Thu, 26 Aug 2021 08:21:34 +0000 David Laight <[email protected]> wrote:

From: Pavel Skripkin

Quoted 10 lines

Sent: 24 August 2021 08:27

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Quoted 7 lines

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 3 lines
(quoted diff) +1 -0
+		len += snprintf(page + len, count - len,

"rtw_read8(0x%x)=0x%x\n",

drivers/staging/r8188eu/core/rtw_debug.c +1 -0
+				proc_get_read_addr, (u8) tmp);

That is broken.

Don't get it, sorry. Previous code did exactly the same thing, but didn't check if read() was successful.

With regards,
Pavel Skripkin

#89 lore raw

RE: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin

From: Pavel Skripkin <[email protected]>

Quoted 10 lines

Sent: 24 August 2021 08:28

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Pretty horrid API interface.
Functions like readl() - which can fail just return ~0u and let the caller worry about whether that causes serious grief.

You could make all the read functions return __u64 and return ~0ull on error.
Testing for (value & 1ull << 63) will be reasonable even on 32bit.

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
drivers/staging/r8188eu/hal/usb_ops_linux.c +6 -2
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32 *data)
 {
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#90 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 12 lines · On Thu, 26 Aug 2021 08:51:23 +0000 David Laight <[email protected]> wrote:

From: Pavel Skripkin <[email protected]>

Quoted 10 lines

Sent: 24 August 2021 08:28

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Quoted 8 lines

Pretty horrid API interface.
Functions like readl() - which can fail just return ~0u and let the caller worry about whether that causes serious grief.

You could make all the read functions return __u64 and return ~0ull on error.
Testing for (value & 1ull << 63) will be reasonable even on 32bit.

I am not the best at API related questions, so can you, please, explain why your approach is better?

As I can see, most of the drivers in usb/ directory use smth like this interface for private reading funcions. We anyway creating tmp variable (but 64 bit _always_) and checking for mistery error, which we cannot pass up to callers.

Sorry, if it's _too_ dumb question, but I really can't get your point....

Quoted 18 lines

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

With regards,
Pavel Skripkin

#91 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 59 lines · Pavel Skripkin
Quoted 12 lines · On Thu, 26 Aug 2021 08:51:23 +0000 David Laight <[email protected]> wrote:

From: Pavel Skripkin <[email protected]>

Quoted 10 lines

Sent: 24 August 2021 08:28

_rtw_read32 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read32() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Quoted 8 lines

Pretty horrid API interface.
Functions like readl() - which can fail just return ~0u and let the caller worry about whether that causes serious grief.

You could make all the read functions return __u64 and return ~0ull on error.
Testing for (value & 1ull << 63) will be reasonable even on 32bit.

I am not the best at API related questions, so can you, please, explain why your approach is better?

As I can see, most of the drivers in usb/ directory use smth like this interface for private reading funcions. We anyway creating tmp variable (but 64 bit _always_) and checking for mistery error, which we cannot pass up to callers.

Sorry, if it's _too_ dumb question, but I really can't get your point....

Quoted 18 lines

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

Quoted 8 lines

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

With regards,
Pavel Skripkin

#63 lore raw

RE: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin

From: Pavel Skripkin

Quoted 25 lines

Sent: 26 August 2021 09:28

Quoted 12 lines · On Thu, 26 Aug 2021 08:21:34 +0000 David Laight <[email protected]> wrote:

From: Pavel Skripkin

Quoted 10 lines

Sent: 24 August 2021 08:27

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

Quoted 7 lines

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 3 lines
(quoted diff) +1 -0
+		len += snprintf(page + len, count - len,

"rtw_read8(0x%x)=0x%x\n",

drivers/staging/r8188eu/core/rtw_debug.c +1 -0
+				proc_get_read_addr, (u8) tmp);

That is broken.

Quoted 2 lines

Don't get it, sorry. Previous code did exactly the same thing, but didn't check if read() was successful.

Look up the return value of snprintf().

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#92 lore raw

RE: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 25 lines
Quoted 25 lines
Quoted 18 lines

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

Quoted 5 lines
Quoted 3 lines

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

maintainer
#49 lore raw

Re: [PATCH v3 2/6] staging: r8188eu: add helper macro for printing registers

In reply to Pavel Skripkin
Quoted 10 lines · Pavel Skripkin

There are a lof of places, where DBG_88E() is used to print register value. Since following patches change _rtw_read*() family prototypes, we can wrap printing registers into useful macro to avoid open-coding error checking like this:

	u32 tmp;
	if (!rtw_read(&tmp))
		DBG("reg = %d\n", tmp);

So, added DBG_88E_REG{8,16,32} macros for printing register values.

No, please work to remove these messy things, do not add new ones.

Why is this ever needed? And if it is, use the correct in-kernel debug functions please.

thanks,

greg k-h

maintainer
#46 lore raw

Re: [PATCH v3 1/6] staging: r8188eu: remove {read,write}_macreg

In reply to Pavel Skripkin
Quoted 7 lines · Pavel Skripkin

These 2 functions are unused, so they can be simply removed

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 39 ------------------------
 drivers/staging/r8188eu/include/rtw_mp.h |  2 --
 2 files changed, 41 deletions(-)

write_macreg_hdl and the read version can also be removed, right?

thanks,

greg k-h

maintainer
#47 lore raw

Re: [PATCH v3 1/6] staging: r8188eu: remove {read,write}_macreg

In reply to Pavel Skripkin
Quoted 7 lines · Pavel Skripkin

These 2 functions are unused, so they can be simply removed

---
 drivers/staging/r8188eu/core/rtw_mp.c    | 39 ------------------------
 drivers/staging/r8188eu/include/rtw_mp.h |  2 --
 2 files changed, 41 deletions(-)

I took this one patch of this series, please redo the rest of them and resend.

thanks,

greg k-h

maintainer
#85 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Pavel Skripkin
Quoted 50 lines · Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  7 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  9 ++---
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  4 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 29 +++++++++++----
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  5 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 37 ++++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 22 +++++++++--
 .../staging/r8188eu/include/odm_interface.h   |  2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  6 +--
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 28 +++++++++++---
 11 files changed, 115 insertions(+), 38 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
index 8b7d3eb12bd0..a41675e101ac 100644
@@ -91,7 +91,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		error = rtw_read16(padapter, proc_get_read_addr, (u16 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n",
+				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
 		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_io.c +0 -0
index 2714506c8ffb..fd64893c778d 100644
@@ -45,18 +45,15 @@ int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 	return _read8(pintfhdl, addr, data);
 }
 

drivers/staging/r8188eu/core/rtw_io.c int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data) · line 54

Quoted 10 lines
drivers/staging/r8188eu/core/rtw_io.c +2 -3
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 {
-	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 
 	_read16 = pintfhdl->io_ops._read16;

Why do you need this extra pointer abstraction anyway? Please unwind that first, which will make this function go away (or get easier to understand at the least...)

thanks,

greg k-h

#93 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to David Laight
Quoted 35 lines · David Laight

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 28 lines
Quoted 28 lines
Quoted 18 lines

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Quoted 8 lines
Quoted 2 lines

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

We not always read in local variable, there are few places, where we read into passed buffer.

With regards,
Pavel Skripkin

#86 lore raw

Re: [PATCH v3 4/6] staging: r8188eu: add error handling of rtw_read16

In reply to Greg KH
Quoted 60 lines · Greg KH
Quoted 59 lines · Pavel Skripkin

_rtw_read16 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read16() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

---
 drivers/staging/r8188eu/core/rtw_debug.c      |  7 +++-
 drivers/staging/r8188eu/core/rtw_io.c         |  9 ++---
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  4 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  4 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 29 +++++++++++----
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  5 ++-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 37 ++++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   | 22 +++++++++--
 .../staging/r8188eu/include/odm_interface.h   |  2 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  6 +--
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 28 +++++++++++---
 11 files changed, 115 insertions(+), 38 deletions(-)
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
index 8b7d3eb12bd0..a41675e101ac 100644
@@ -91,7 +91,12 @@ int proc_get_read_reg(char *page, char **start,
 				proc_get_read_addr, (u8) tmp);
 		break;
 	case 2:
-		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+		error = rtw_read16(padapter, proc_get_read_addr, (u16 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read16(0x%x)=0x%x\n",
+				proc_get_read_addr, (u16) tmp);
 		break;
 	case 4:
 		len += snprintf(page + len, count - len, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
drivers/staging/r8188eu/core/rtw_io.c +2 -3
index 2714506c8ffb..fd64893c778d 100644
@@ -45,18 +45,15 @@ int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
 	return _read8(pintfhdl, addr, data);
 }
 
-u16 _rtw_read16(struct adapter *adapter, u32 addr)
+int __must_check _rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
 {
-	u16 r_val;
 	struct io_priv *pio_priv = &adapter->iopriv;
 	struct	intf_hdl		*pintfhdl = &pio_priv->intf;
-	u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	int (*_read16)(struct intf_hdl *pintfhdl, u32 addr, u16 *data);
 
Quoted 6 lines

drivers/staging/r8188eu/core/rtw_io.c int __must_check _rtw_read8(struct adapter *adapter, u32 addr, u8 *data) · line 54

Quoted 1 line
drivers/staging/r8188eu/core/rtw_io.c +0 -0
 	_read16 = pintfhdl->io_ops._read16;

Why do you need this extra pointer abstraction anyway? Please unwind that first, which will make this function go away (or get easier to understand at the least...)

It was there before my changes :) I had a plan to clean up DBG macros and this abstraction after adding error handling...

If you feel, that these clean up are needed before error handling, I can add them to this series :) Anyway, some of them are already in my local tree

With regards,
Pavel Skripkin

#94 lore raw

RE: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to Pavel Skripkin

From: Pavel Skripkin

Quoted 42 lines

Sent: 26 August 2021 11:55

Quoted 39 lines · David Laight

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 30 lines
Quoted 20 lines
Quoted 18 lines

...

drivers/staging/r8188eu/hal/usb_ops_linux.c static int usb_read16(struct intf_hdl *pintfhdl, u32 addr, u16 *data) · line 166

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

drivers/staging/r8188eu/hal/usb_ops_linux.c +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

Quoted 8 lines

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

Quoted 7 lines
Quoted 4 lines

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

We not always read in local variable, there are few places, where we read into passed buffer.

It is still a very local coding bug.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#58 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Nick Desaulniers
Quoted 60 lines · Nick Desaulniers
Quoted 59 lines · Pavel Skripkin
Quoted 39 lines · Dan Carpenter
Quoted 23 lines · Pavel Skripkin
Quoted 13 lines

This is not related to your patch. Ignore it.

Quoted 9 lines
Quoted 6 lines

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

2020 case HW_VAR_BCN_VALID:
2021 /* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */

Quoted 1 line

2022 u8 tmp;

Hm, I don't know anything about ARM compilers, so should I wrap this code block with {}?

Quoted 9 lines

Yep.

Quoted 3 lines

My local gcc 11.1.1 (x86_64) does not produce any warnings/errors

You should figure out whats up with that because it shouldn't compile with the gcc options that the kernel uses.

Quoted 5 lines

AFAIK, at least 2 guys except me in this CC list compiled my series without errors/warnings. Maybe, staging tree is missing some Makefile updates?

I'll resend series this evening anyway, but this is strange....

Hm... In my version of GCC the error is:

drivers/staging/r8188eu/hal/usb_halinit.c:1870:3: error: a label can only be part of a statement and a declaration is not a statement

That's a different error from what I was expecting. It's caused by having a declaration directly after a case statement. The warning that I was expecting was from -Wdeclaration-after-statement and it looks like this:

Quoted 5 lines

warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]

You really should try investigate why this compiles for you because something is going wrong. It should not build without a warning.

Looks like it's bug in gcc 11.1.1. I've rebuilt this module with gcc 10 (gcc-10 (SUSE Linux) 10.3.1 20210707 [revision 048117e16c77f82598fca9af585500572d46ad73]) and build fails with error described above

My default gcc is

gcc (SUSE Linux) 11.1.1 20210721 [revision
076930b9690ac3564638636f6b13bbb6bc608aea]

Quoted 5 lines
Quoted 1 line

Any idea? :)

The original report said the build was with clang-14, which is near top of tree and unreleased. It's possible that that build had a bug that hopefully was reverted.

No, Clang is right to refuse to build the code. It's GCC 11.1.1 which is wrong because it allows it. I'm not C language expert but we're using the -Wdeclaration-after-statement because we don't want this.

regards,
dan carpenter

#64 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to David Laight
Quoted 26 lines · David Laight

From: Pavel Skripkin

Quoted 25 lines

Sent: 26 August 2021 09:28

Quoted 19 lines · On Thu, 26 Aug 2021 08:21:34 +0000 David Laight <[email protected]> wrote:

From: Pavel Skripkin

Quoted 10 lines

Sent: 24 August 2021 08:27

_rtw_read8 function can fail in case of usb transfer failure. But previous function prototype wasn't designed to return an error to caller. It can cause a lot uninit value bugs all across the driver code, since rtw_read8() returns local stack variable to caller.

Fix it by changing the prototype of this function. Now it returns an
int: 0 on success, negative error value on failure and callers should pass the pointer to storage location for register value.

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 3 lines
(quoted diff) +1 -0
+		len += snprintf(page + len, count - len,

"rtw_read8(0x%x)=0x%x\n",

drivers/staging/r8188eu/core/rtw_debug.c +1 -0
+				proc_get_read_addr, (u8) tmp);

That is broken.

Quoted 5 lines
Quoted 2 lines

Don't get it, sorry. Previous code did exactly the same thing, but didn't check if read() was successful.

Look up the return value of snprintf().

It's hard to understand what you are saying. I think you are confusing libc snprintf with the kernel snprintf? In libc the snprintf function can return negatives but in the kernel it cannot. This is not going to change. Any code which checks for negative snprintf returns in the kernel is wrong and should be fixed.

Anyway, the code works fine. snprintf here is going to return a number between 18-32 range. It's not going to overflow the PAGE_SIZE buffer.

It would be nicer to use scnprint() but that's an unrelated patch.

Also this is all dead code. It needs to be converted to sysfs. The caller is ifdeffed out because it doesn't compile.

regards,
dan carpenter

#95 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

In reply to David Laight
Quoted 48 lines · David Laight

From: Pavel Skripkin

Quoted 47 lines

Sent: 26 August 2021 11:55

Quoted 43 lines · David Laight

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 25 lines
Quoted 25 lines
Quoted 18 lines

...

Review

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

(quoted diff) +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

Quoted 5 lines
Quoted 3 lines

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

Quoted 7 lines
Quoted 2 lines

We not always read in local variable, there are few places, where we read into passed buffer.

It is still a very local coding bug.

David

Sure, but is defensive programming so bad?

Greg, what your opinion about this NULL check?

With regards,
Pavel Skripkin

#96 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 52 lines · Pavel Skripkin
Quoted 51 lines · David Laight

From: Pavel Skripkin

Quoted 49 lines

Sent: 26 August 2021 11:55

Quoted 35 lines · David Laight

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 28 lines
Quoted 28 lines
Quoted 18 lines

...

Review

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

(quoted diff) +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Quoted 8 lines
Quoted 2 lines

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

We not always read in local variable, there are few places, where we read into passed buffer.

Quoted 6 lines
Quoted 4 lines

It is still a very local coding bug.

David

Sure, but is defensive programming so bad?

Yes it is, for when it is not needed.

Quoted 1 line

Greg, what your opinion about this NULL check?

Never check for things that you know are not going to happen. Otherwise the kernel would just be full of pointless checks everywhere.

And why are you waiting for me to tell you this? Why do you not believe David?

thanks,

greg k-h

#97 lore raw

Re: [PATCH v3 5/6] staging: r8188eu: add error handling of rtw_read32

Quoted 62 lines · On 8/27/21 10:12 AM, [email protected] wrote:
Quoted 52 lines · Pavel Skripkin
Quoted 51 lines · David Laight

From: Pavel Skripkin

Quoted 49 lines

Sent: 26 August 2021 11:55

Quoted 35 lines · David Laight

From: Pavel Skripkin

Quoted 5 lines

Sent: 26 August 2021 10:28

Quoted 2 lines · Pavel Skripkin

On Thu, 26 Aug 2021 08:51:23 +0000
David Laight <[email protected]> wrote:

...

Quoted 28 lines
Quoted 28 lines
Quoted 18 lines

...

Review

Quoted 13 lines
(quoted diff) +1 -1
-static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
+static int usb_read32(struct intf_hdl *pintfhdl, u32 addr, u32

*data) {

(quoted diff) +5 -1
 	u8 requesttype;
 	u16 wvalue;
 	u16 len;
-	__le32 data;
+	int res;
+	__le32 tmp;
+
+	if (WARN_ON(unlikely(!data)))
+		return -EINVAL;

Kill the NULL check - it is a silly coding error.
An OOPS is just as easy to debug.

I don't think that one single driver should kill the whole system. It's 100% an error, but kernel can recover from it (for example disconnect the driver, since it's broken).

AFIAK, Greg and Linus do not like BUG_ONs in recoverable state... Correct me, if I am wrong

Quoted 8 lines
Quoted 2 lines

Oops, I thought about BUG_ON() instead of WARN_ON(), sorry for confusion. My point is "we should not let the box boom".

There is no point checking for NULL that just can't happen. In this case all the callers will pass the address of a local. There really is no point checking.

We not always read in local variable, there are few places, where we read into passed buffer.

Quoted 6 lines
Quoted 4 lines

It is still a very local coding bug.

David

Sure, but is defensive programming so bad?

Yes it is, for when it is not needed.

Quoted 8 lines
Quoted 1 line

Greg, what your opinion about this NULL check?

Never check for things that you know are not going to happen. Otherwise the kernel would just be full of pointless checks everywhere.

And why are you waiting for me to tell you this? Why do you not believe David?

Just wanted to hear more opinions on this check. I believe David, but opinions of other people are important too, IMO

With regards,
Pavel Skripkin

#100 lore raw
In reply to Pavel Skripkin
Quoted 9 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

Quoted 8 lines

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

v2 -> v3:

Hi Pavel.

If v4 is needed can you please send it without replying to old message. This thread is so hard to follow because always new version is answer to old subject. This depens a little bit how you setup your email, but some of us is grouping all emails in same thread and this thread is out of control :D

Thanks
Kari Argillander

Quoted 64 lines

1. Fixed OOPS in usb_read32(), caused by writing to u32 **
2. Fixed style in rtw_read32, rtw_read16 and rtw_read8 (Suggested by Dan)
3. Added error hanling when usb_control_msg() returns ret != len
NOTE: Dan suggested to add this to usbctrl_vendorreq(), but there is pending series, which will get rid of usb_control_msg(), so (res != len) check can be removed, when Fabio's series will go in
4. Removed RFC tag

v1 -> v2:
1. Make rtw_read*() return an error instead of initializing pointer to error
2. Split one huge patch to smaller ones for each rtw_read{8,16,32} function changes
3. Add new macro for printing register values (It helps to not copy-paste error handling)
4. Removed {read,write}_macreg (Suggested by Phillip)
5. Rebased on top of staging-next
6. Cleaned checkpatch errors and warnings

Phillip has tested fixed v2 version, AFAIU

Pavel Skripkin (6):
staging: r8188eu: remove {read,write}_macreg
staging: r8188eu: add helper macro for printing registers
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
staging: r8188eu: make ReadEFuse return an int

 drivers/staging/r8188eu/core/rtw_debug.c      |  79 +++-
 drivers/staging/r8188eu/core/rtw_efuse.c      | 125 +++--
 drivers/staging/r8188eu/core/rtw_io.c         |  27 +-
 drivers/staging/r8188eu/core/rtw_mp.c         |  70 ++-
 drivers/staging/r8188eu/core/rtw_mp_ioctl.c   |  13 +-
 drivers/staging/r8188eu/core/rtw_pwrctrl.c    |   5 +-
 drivers/staging/r8188eu/core/rtw_sreset.c     |   9 +-
 .../r8188eu/hal/Hal8188ERateAdaptive.c        |   8 +-
 drivers/staging/r8188eu/hal/HalPhyRf_8188e.c  |  21 +-
 drivers/staging/r8188eu/hal/HalPwrSeqCmd.c    |   9 +-
 drivers/staging/r8188eu/hal/hal_com.c         |  23 +-
 drivers/staging/r8188eu/hal/hal_intf.c        |   6 +-
 drivers/staging/r8188eu/hal/odm_interface.c   |  12 +-
 drivers/staging/r8188eu/hal/rtl8188e_cmd.c    |  33 +-
 drivers/staging/r8188eu/hal/rtl8188e_dm.c     |   6 +-
 .../staging/r8188eu/hal/rtl8188e_hal_init.c   | 285 +++++++++---
 drivers/staging/r8188eu/hal/rtl8188e_phycfg.c |  27 +-
 drivers/staging/r8188eu/hal/rtl8188e_sreset.c |  22 +-
 drivers/staging/r8188eu/hal/rtl8188eu_led.c   |  18 +-
 drivers/staging/r8188eu/hal/usb_halinit.c     | 439 +++++++++++++++---
 drivers/staging/r8188eu/hal/usb_ops_linux.c   |  62 ++-
 drivers/staging/r8188eu/include/hal_intf.h    |   6 +-
 .../staging/r8188eu/include/odm_interface.h   |   6 +-
 .../staging/r8188eu/include/rtl8188e_hal.h    |   2 +-
 drivers/staging/r8188eu/include/rtw_debug.h   |  13 +
 drivers/staging/r8188eu/include/rtw_efuse.h   |   4 +-
 drivers/staging/r8188eu/include/rtw_io.h      |  18 +-
 drivers/staging/r8188eu/include/rtw_mp.h      |   2 -
 drivers/staging/r8188eu/os_dep/ioctl_linux.c  | 179 +++++--
 drivers/staging/r8188eu/os_dep/usb_intf.c     |   3 +-
 30 files changed, 1143 insertions(+), 389 deletions(-)
Signature · 1 line
2.32.0
#101 lore raw
Quoted 19 lines · Kari Argillander
Quoted 9 lines · Pavel Skripkin

Hi, Greg, Larry and Phillip!

I noticed, that new staging driver was added like 3 weeks ago and I decided to look at the code, because drivers in staging directory are always buggy.

The first thing I noticed is *no one* was checking read operations result, but it can fail and driver may start writing random stack values into registers. It can cause driver misbehavior or device misbehavior.

Quoted 8 lines

To avoid this type of bugs, i've changed rtw_read* API. Now all rtw_read funtions return an error, when something went wrong with usb transfer.

It helps callers to break/return earlier and don't write random values to registers or to rely on random values.

v2 -> v3:

Quoted 8 lines

Hi Pavel.

If v4 is needed can you please send it without replying to old message. This thread is so hard to follow because always new version is answer to old subject. This depens a little bit how you setup your email, but some of us is grouping all emails in same thread and this thread is out of control :D

Hi, Kari!

v4 will be posted soon, yep. I will post v4 as separate thread :) It's unreal to follow the discussion for sure. I often spend about a minute to find an actual mail to reply xd

With regards,
Pavel Skripkin

#65 lore raw

RE: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Dan Carpenter

From: Dan Carpenter

Quoted 1 line

Sent: 26 August 2021 12:21

...

Quoted 14 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 3 lines
(quoted diff) +1 -0
+		len += snprintf(page + len, count - len,

"rtw_read8(0x%x)=0x%x\n",

drivers/staging/r8188eu/core/rtw_debug.c +1 -0
+				proc_get_read_addr, (u8) tmp);

That is broken.

Quoted 5 lines
Quoted 2 lines

Don't get it, sorry. Previous code did exactly the same thing, but didn't check if read() was successful.

Look up the return value of snprintf().

Quoted 8 lines

It's hard to understand what you are saying. I think you are confusing libc snprintf with the kernel snprintf? In libc the snprintf function can return negatives but in the kernel it cannot. This is not going to change. Any code which checks for negative snprintf returns in the kernel is wrong and should be fixed.

Anyway, the code works fine. snprintf here is going to return a number between 18-32 range. It's not going to overflow the PAGE_SIZE buffer.

IIRC it is also in a loop ...

Maybe, but the idiom is just broken.
Largely the result of snprintf() is never the value you are looking for and should be ignored.

Userspace fprintf() is even worse.
If you care about the write failing you need to call fflush() and then ferror() (typically before fclose()).

Fortunately I've never seen a 'must check' attribute on it.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

#66 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 23 lines · David Laight

From: Dan Carpenter

Quoted 1 line

Sent: 26 August 2021 12:21

...

Quoted 20 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

...

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 3 lines
(quoted diff) +1 -0
+		len += snprintf(page + len, count - len,

"rtw_read8(0x%x)=0x%x\n",

drivers/staging/r8188eu/core/rtw_debug.c +1 -0
+				proc_get_read_addr, (u8) tmp);

That is broken.

Quoted 5 lines
Quoted 2 lines

Don't get it, sorry. Previous code did exactly the same thing, but didn't check if read() was successful.

Look up the return value of snprintf().

It's hard to understand what you are saying. I think you are confusing libc snprintf with the kernel snprintf? In libc the snprintf function can return negatives but in the kernel it cannot. This is not going to change. Any code which checks for negative snprintf returns in the kernel is wrong and should be fixed.

Quoted 9 lines
Quoted 2 lines

Anyway, the code works fine. snprintf here is going to return a number between 18-32 range. It's not going to overflow the PAGE_SIZE buffer.

IIRC it is also in a loop ...

Maybe, but the idiom is just broken.
Largely the result of snprintf() is never the value you are looking for and should be ignored.

AFAIK, snprintf return value is largely used in sysfs at least.

$ grep -Ir "= snprintf" | wc -l
1200

Anyway, I will convert this dead code to sysfs interface and maybe snprintf will go away...

Thank you for your help and comments

Quoted 4 lines

Userspace fprintf() is even worse.
If you care about the write failing you need to call fflush() and then ferror() (typically before fclose()).

Quoted 8 lines

Fortunately I've never seen a 'must check' attribute on it.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)

With regards,
Pavel Skripkin

#67 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 92

Quoted 12 lines · Pavel Skripkin
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
@@ -83,7 +83,12 @@ int proc_get_read_reg(char *page, char **start,
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		error = rtw_read8(padapter, proc_get_read_addr, (u8 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);
 		break;

Oh my goodness... :P

If you look at what proc_get_read_addr is, it turns out it's a 32bit address which is controlled by the user in proc_set_read_reg(). LOL! Just a giant security hole.

My advise is just delete this dead code. No one is using it so how necessary can it be?

regards,
dan carpenter

#68 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 16 lines · Dan Carpenter

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 92

Quoted 12 lines · Pavel Skripkin
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
@@ -83,7 +83,12 @@ int proc_get_read_reg(char *page, char **start,
 
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		error = rtw_read8(padapter, proc_get_read_addr, (u8 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);
 		break;

Oh my goodness... :P

Quoted 6 lines

If you look at what proc_get_read_addr is, it turns out it's a 32bit address which is controlled by the user in proc_set_read_reg(). LOL! Just a giant security hole.

My advise is just delete this dead code. No one is using it so how necessary can it be?

Yep, it's dead code as was already mentioned. My plan is to convert all this code to sysfs. One thing I am wondering about should I include these changes into this series?...

With regards,
Pavel Skripkin

#69 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

Quoted 20 lines · Pavel Skripkin
Quoted 19 lines · Dan Carpenter

drivers/staging/r8188eu/core/rtw_debug.c int proc_get_read_reg(char *page, char **start, · line 91

Quoted 11 lines · Pavel Skripkin
drivers/staging/r8188eu/core/rtw_debug.c +6 -1
@@ -83,7 +83,12 @@ int proc_get_read_reg(char *page, char **start,
 	switch (proc_get_read_len) {
 	case 1:
-		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+		error = rtw_read8(padapter, proc_get_read_addr, (u8 *) &tmp);
+		if (error)
+			return len;
+
+		len += snprintf(page + len, count - len, "rtw_read8(0x%x)=0x%x\n",
+				proc_get_read_addr, (u8) tmp);
 		break;

Oh my goodness... :P

If you look at what proc_get_read_addr is, it turns out it's a 32bit address which is controlled by the user in proc_set_read_reg(). LOL! Just a giant security hole.

Quoted 6 lines
Quoted 2 lines

My advise is just delete this dead code. No one is using it so how necessary can it be?

Yep, it's dead code as was already mentioned. My plan is to convert all this code to sysfs.

I thought this was a good plan until a few minutes ago when I noticed it was a ***GIANT SECURITY HOLE***! :P

I mean presumably this is root controlled but these days we try to restrict root as well in some ways. Even confined to root only, this code is incredibly risky and bad. Don't convert it. Just delete it.

regards,
dan carpenter

#70 lore raw

Re: [PATCH v3 3/6] staging: r8188eu: add error handling of rtw_read8

In reply to Pavel Skripkin
Thank you for the patch! Yet something to improve:

Hi Pavel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/d4e4bbed4e59df37967086f60fe92cb1b4504d37
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Pavel-Skripkin/staging-r8188eu-remove-read-write-_macreg/20210824-162756
        git checkout d4e4bbed4e59df37967086f60fe92cb1b4504d37
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/staging/r8188eu/

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

drivers/staging/r8188eu/hal/usb_halinit.c: In function 'SetHwReg8188EU':

>> drivers/staging/r8188eu/hal/usb_halinit.c:2022:3: error: a label can only be part of a statement and a declaration is not a statement
    2022 |   u8 tmp;
         |   ^~

vim +2022 drivers/staging/r8188eu/hal/usb_halinit.c

1450
1451 static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
1452 {
1453 struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
1454 struct dm_priv *pdmpriv = &haldata->dmpriv;
1455 struct odm_dm_struct *podmpriv = &haldata->odmpriv;
1456 int error;
1457 u8 tmp;
1458
1459 switch (variable) {
1460 case HW_VAR_MEDIA_STATUS:
1461 {
1462 u8 val8;
1463
1464 error = rtw_read8(Adapter, MSR, &val8);
1465 if (error)
1466 return;
1467
1468 val8 &= 0x0c;
1469 val8 |= *((u8 *)val);
1470 rtw_write8(Adapter, MSR, val8);
1471 }
1472 break;
1473 case HW_VAR_MEDIA_STATUS1:
1474 {
1475 u8 val8;
1476
1477 error = rtw_read8(Adapter, MSR, &val8);
1478 if (error)
1479 return;
1480
1481 val8 &= 0x03;
1482 val8 |= *((u8 *)val) << 2;
1483 rtw_write8(Adapter, MSR, val8);
1484 }
1485 break;
1486 case HW_VAR_SET_OPMODE:
1487 hw_var_set_opmode(Adapter, variable, val);
1488 break;
1489 case HW_VAR_MAC_ADDR:
1490 hw_var_set_macaddr(Adapter, variable, val);
1491 break;
1492 case HW_VAR_BSSID:
1493 hw_var_set_bssid(Adapter, variable, val);
1494 break;
1495 case HW_VAR_BASIC_RATE:
1496 {
1497 u16 BrateCfg = 0;
1498 u8 RateIndex = 0;
1499

  1500				/*  2007.01.16, by Emily */
  1501				/*  Select RRSR (in Legacy-OFDM and CCK) */
  1502				/*  For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */
  1503				/*  We do not use other rates. */
  1504				HalSetBrateCfg(Adapter, val, &BrateCfg);
  1505				DBG_88E("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg);
  1506	
  1507				/* 2011.03.30 add by Luke Lee */
  1508				/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
  1509				/* because CCK 2M has poor TXEVM */
  1510				/* CCK 5.5M & 11M ACK should be enabled for better performance */
  1511	
  1512				BrateCfg = (BrateCfg | 0xd) & 0x15d;
  1513				haldata->BasicRateSet = BrateCfg;
  1514	
  1515				BrateCfg |= 0x01; /*  default enable 1M ACK rate */
  1516				/*  Set RRSR rate table. */
  1517				rtw_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
  1518				rtw_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff);
  1519	
  1520				error = rtw_read8(Adapter, REG_RRSR + 2, &tmp);
  1521				if (error)
  1522					return;
  1523	
  1524				rtw_write8(Adapter, REG_RRSR + 2, tmp & 0xf0);
  1525	
  1526				/*  Set RTS initial rate */
  1527				while (BrateCfg > 0x1) {
  1528					BrateCfg = (BrateCfg >> 1);
  1529					RateIndex++;
  1530				}
  1531				/*  Ziv - Check */
  1532				rtw_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
  1533			}
  1534			break;
  1535		case HW_VAR_TXPAUSE:
  1536			rtw_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
  1537			break;
  1538		case HW_VAR_BCN_FUNC:
  1539			hw_var_set_bcn_func(Adapter, variable, val);
  1540			break;
  1541		case HW_VAR_CORRECT_TSF:
  1542			{
  1543				u64	tsf;
  1544				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1545				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1546	
  1547				tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue,
  1548								  pmlmeinfo->bcn_interval * 1024) - 1024; /* us */
  1549	
  1550				if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
  1551					StopTxBeacon(Adapter);
  1552	
  1553				/* disable related TSF function */
  1554				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1555				if (error)
  1556					return;
  1557	
  1558				rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(3)));
  1559	
  1560				rtw_write32(Adapter, REG_TSFTR, tsf);
  1561				rtw_write32(Adapter, REG_TSFTR + 4, tsf >> 32);
  1562	
  1563				/* enable related TSF function */
  1564				error =  rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1565				if (error)
  1566					return;
  1567	
  1568				rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(3));
  1569	
  1570				if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
  1571					ResumeTxBeacon(Adapter);
  1572			}
  1573			break;
  1574		case HW_VAR_CHECK_BSSID:
  1575			if (*((u8 *)val)) {
  1576				rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1577			} else {
  1578				u32 val32;
  1579	
  1580				val32 = rtw_read32(Adapter, REG_RCR);
  1581	
  1582				val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1583	
  1584				rtw_write32(Adapter, REG_RCR, val32);
  1585			}
  1586			break;
  1587		case HW_VAR_MLME_DISCONNECT:
  1588			/* Set RCR to not to receive data frame when NO LINK state */
  1589			/* reject all data frames */
  1590			rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1591	
  1592			/* reset TSF */
  1593			rtw_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
  1594	
  1595			/* disable update TSF */
  1596			error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1597			if (error)
  1598				return;
  1599	
  1600			rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(4));
  1601			break;
  1602		case HW_VAR_MLME_SITESURVEY:
  1603			if (*((u8 *)val)) { /* under sitesurvey */
  1604				/* config RCR to receive different BSSID & not to receive data frame */
  1605				u32 v = rtw_read32(Adapter, REG_RCR);
  1606	
  1607				v &= ~(RCR_CBSSID_BCN);
  1608				rtw_write32(Adapter, REG_RCR, v);
  1609				/* reject all data frame */
  1610				rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1611	
  1612				/* disable update TSF */
  1613				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1614				if (error)
  1615					return;
  1616				rtw_write8(Adapter, REG_BCN_CTRL, tmp | BIT(4));
  1617			} else { /* sitesurvey done */
  1618				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1619				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1620	
  1621				error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1622				if (error)
  1623					return;
  1624	
  1625				if ((is_client_associated_to_ap(Adapter)) ||
  1626				    ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
  1627					/* enable to rx data frame */
  1628					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1629	
  1630					/* enable update TSF */
  1631					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1632				} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  1633					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1634					/* enable update TSF */
  1635					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1636				}
  1637	
  1638				if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  1639					rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
  1640				} else {
  1641					if (Adapter->in_cta_test) {
  1642						u32 v = rtw_read32(Adapter, REG_RCR);
  1643						v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
  1644						rtw_write32(Adapter, REG_RCR, v);
  1645					} else {
  1646						rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
  1647					}
  1648				}
  1649			}
  1650			break;
  1651		case HW_VAR_MLME_JOIN:
  1652			{
  1653				u8 RetryLimit = 0x30;
  1654				u8 type = *((u8 *)val);
  1655				u8 tmp;
  1656				struct mlme_priv	*pmlmepriv = &Adapter->mlmepriv;
  1657	
  1658				if (type == 0) { /*  prepare to join */
  1659					/* enable to rx data frame.Accept all data frame */
  1660					rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
  1661	
  1662					if (Adapter->in_cta_test) {
  1663						u32 v = rtw_read32(Adapter, REG_RCR);
  1664						v &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/*  RCR_ADF */
  1665						rtw_write32(Adapter, REG_RCR, v);
  1666					} else {
  1667						rtw_write32(Adapter, REG_RCR, rtw_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
  1668					}
  1669	
  1670					if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
  1671						RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48;
  1672					else /*  Ad-hoc Mode */
  1673						RetryLimit = 0x7;
  1674				} else if (type == 1) {
  1675					/* joinbss_event call back when join res < 0 */
  1676					rtw_write16(Adapter, REG_RXFLTMAP2, 0x00);
  1677				} else if (type == 2) {
  1678					/* sta add event call back */
  1679					/* enable update TSF */
  1680					error = rtw_read8(Adapter, REG_BCN_CTRL, &tmp);
  1681					if (error)
  1682						return;
  1683	
  1684					rtw_write8(Adapter, REG_BCN_CTRL, tmp & (~BIT(4)));
  1685	
  1686					if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
  1687						RetryLimit = 0x7;
  1688				}
  1689				rtw_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
  1690			}
  1691			break;
  1692		case HW_VAR_BEACON_INTERVAL:
  1693			rtw_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
  1694			break;
  1695		case HW_VAR_SLOT_TIME:
  1696			{
  1697				u8 u1bAIFS, aSifsTime;
  1698				struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
  1699				struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
  1700	
  1701				rtw_write8(Adapter, REG_SLOT, val[0]);
  1702	
  1703				if (pmlmeinfo->WMM_enable == 0) {
  1704					if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
  1705						aSifsTime = 10;
  1706					else
  1707						aSifsTime = 16;
  1708	
  1709					u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
  1710	
  1711					/*  <Roger_EXP> Temporary removed, 2008.06.20. */
  1712					rtw_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
  1713					rtw_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
  1714					rtw_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
  1715					rtw_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
  1716				}
  1717			}
  1718			break;
  1719		case HW_VAR_RESP_SIFS:
  1720			/* RESP_SIFS for CCK */
  1721			rtw_write8(Adapter, REG_R2T_SIFS, val[0]); /*  SIFS_T2T_CCK (0x08) */
  1722			rtw_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */
  1723			/* RESP_SIFS for OFDM */
  1724			rtw_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
  1725			rtw_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
  1726			break;
  1727		case HW_VAR_ACK_PREAMBLE:
  1728			{
  1729				u8 regTmp;
  1730				u8 bShortPreamble = *((bool *)val);
  1731				/*  Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
  1732				regTmp = (haldata->nCur40MhzPrimeSC) << 5;
  1733				if (bShortPreamble)
  1734					regTmp |= 0x80;
  1735	
  1736				rtw_write8(Adapter, REG_RRSR + 2, regTmp);
  1737			}
  1738			break;
  1739		case HW_VAR_SEC_CFG:
  1740			rtw_write8(Adapter, REG_SECCFG, *((u8 *)val));
  1741			break;
  1742		case HW_VAR_DM_FLAG:
  1743			podmpriv->SupportAbility = *((u8 *)val);
  1744			break;
  1745		case HW_VAR_DM_FUNC_OP:
  1746			if (val[0])
  1747				podmpriv->BK_SupportAbility = podmpriv->SupportAbility;
  1748			else
  1749				podmpriv->SupportAbility = podmpriv->BK_SupportAbility;
  1750			break;
  1751		case HW_VAR_DM_FUNC_SET:
  1752			if (*((u32 *)val) == DYNAMIC_ALL_FUNC_ENABLE) {
  1753				pdmpriv->DMFlag = pdmpriv->InitDMFlag;
  1754				podmpriv->SupportAbility =	pdmpriv->InitODMFlag;
  1755			} else {
  1756				podmpriv->SupportAbility |= *((u32 *)val);
  1757			}
  1758			break;
  1759		case HW_VAR_DM_FUNC_CLR:
  1760			podmpriv->SupportAbility &= *((u32 *)val);
  1761			break;
  1762		case HW_VAR_CAM_EMPTY_ENTRY:
  1763			{
  1764				u8 ucIndex = *((u8 *)val);
  1765				u8 i;
  1766				u32 ulCommand = 0;
  1767				u32 ulContent = 0;
  1768				u32 ulEncAlgo = CAM_AES;
  1769	
  1770				for (i = 0; i < CAM_CONTENT_COUNT; i++) {
  1771					/*  filled id in CAM config 2 byte */
  1772					if (i == 0)
  1773						ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2);
  1774					else
  1775						ulContent = 0;
  1776					/*  polling bit, and No Write enable, and address */
  1777					ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
  1778					ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
  1779					/*  write content 0 is equall to mark invalid */
  1780					rtw_write32(Adapter, WCAMI, ulContent);  /* delay_ms(40); */
  1781					rtw_write32(Adapter, RWCAM, ulCommand);  /* delay_ms(40); */
  1782				}
  1783			}
  1784			break;
  1785		case HW_VAR_CAM_INVALID_ALL:
  1786			rtw_write32(Adapter, RWCAM, BIT(31) | BIT(30));
  1787			break;
  1788		case HW_VAR_CAM_WRITE:
  1789			{
  1790				u32 cmd;
  1791				u32 *cam_val = (u32 *)val;
  1792				rtw_write32(Adapter, WCAMI, cam_val[0]);
  1793	
  1794				cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
  1795				rtw_write32(Adapter, RWCAM, cmd);
  1796			}
  1797			break;
  1798		case HW_VAR_AC_PARAM_VO:
  1799			rtw_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
  1800			break;
  1801		case HW_VAR_AC_PARAM_VI:
  1802			rtw_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
  1803			break;
  1804		case HW_VAR_AC_PARAM_BE:
  1805			haldata->AcParam_BE = ((u32 *)(val))[0];
  1806			rtw_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
  1807			break;
  1808		case HW_VAR_AC_PARAM_BK:
  1809			rtw_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
  1810			break;
  1811		case HW_VAR_ACM_CTRL:
  1812			{
  1813				u8 acm_ctrl = *((u8 *)val);
  1814				u8 AcmCtrl;
  1815	
  1816				error = rtw_read8(Adapter, REG_ACMHWCTRL, &AcmCtrl);
  1817				if (error)
  1818					return;
  1819	
  1820				if (acm_ctrl > 1)
  1821					AcmCtrl = AcmCtrl | 0x1;
  1822	
  1823				if (acm_ctrl & BIT(3))
  1824					AcmCtrl |= AcmHw_VoqEn;
  1825				else
  1826					AcmCtrl &= (~AcmHw_VoqEn);
  1827	
  1828				if (acm_ctrl & BIT(2))
  1829					AcmCtrl |= AcmHw_ViqEn;
  1830				else
  1831					AcmCtrl &= (~AcmHw_ViqEn);
  1832	
  1833				if (acm_ctrl & BIT(1))
  1834					AcmCtrl |= AcmHw_BeqEn;
  1835				else
  1836					AcmCtrl &= (~AcmHw_BeqEn);
  1837	
  1838				DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
  1839				rtw_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
  1840			}
  1841			break;
  1842		case HW_VAR_AMPDU_MIN_SPACE:
  1843			{
  1844				u8 MinSpacingToSet;
  1845				u8 SecMinSpace;
  1846				u8 tmp;
  1847	
  1848				MinSpacingToSet = *((u8 *)val);
  1849				if (MinSpacingToSet <= 7) {
  1850					switch (Adapter->securitypriv.dot11PrivacyAlgrthm) {
  1851					case _NO_PRIVACY_:
  1852					case _AES_:
  1853						SecMinSpace = 0;
  1854						break;
  1855					case _WEP40_:
  1856					case _WEP104_:
  1857					case _TKIP_:
  1858					case _TKIP_WTMIC_:
  1859						SecMinSpace = 6;
  1860						break;
  1861					default:
  1862						SecMinSpace = 7;
  1863						break;
  1864					}
  1865					if (MinSpacingToSet < SecMinSpace)
  1866						MinSpacingToSet = SecMinSpace;
  1867	
  1868					error = rtw_read8(Adapter, REG_AMPDU_MIN_SPACE, &tmp);
  1869					if (error)
  1870						return;
  1871	
  1872					rtw_write8(Adapter, REG_AMPDU_MIN_SPACE, (tmp & 0xf8) |
  1873						  MinSpacingToSet);
  1874				}
  1875			}
  1876			break;
  1877		case HW_VAR_AMPDU_FACTOR:
  1878			{
  1879				u8 RegToSet_Normal[4] = {0x41, 0xa8, 0x72, 0xb9};
  1880				u8 FactorToSet;
  1881				u8 *pRegToSet;
  1882				u8 index = 0;
  1883	
  1884				pRegToSet = RegToSet_Normal; /*  0xb972a841; */
  1885				FactorToSet = *((u8 *)val);
  1886				if (FactorToSet <= 3) {
  1887					FactorToSet = (1 << (FactorToSet + 2));
  1888					if (FactorToSet > 0xf)
  1889						FactorToSet = 0xf;
  1890	
  1891					for (index = 0; index < 4; index++) {
  1892						if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
  1893							pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4);
  1894	
  1895						if ((pRegToSet[index] & 0x0f) > FactorToSet)
  1896							pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet);
  1897	
  1898						rtw_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]);
  1899					}
  1900				}
  1901			}
  1902			break;
  1903		case HW_VAR_RXDMA_AGG_PG_TH:
  1904			{
  1905				u8 threshold = *((u8 *)val);
  1906				if (threshold == 0)
  1907					threshold = haldata->UsbRxAggPageCount;
  1908				rtw_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
  1909			}
  1910			break;
  1911		case HW_VAR_SET_RPWM:
  1912			break;
  1913		case HW_VAR_H2C_FW_PWRMODE:
  1914			{
  1915				u8 psmode = (*(u8 *)val);
  1916	
  1917				/*  Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
  1918				/*  saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
  1919				if ((psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(haldata->VersionID)))
  1920					ODM_RF_Saving(podmpriv, true);
  1921				rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
  1922			}
  1923			break;
  1924		case HW_VAR_H2C_FW_JOINBSSRPT:
  1925			{
  1926				u8 mstatus = (*(u8 *)val);
  1927				rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus);
  1928			}
  1929			break;
  1930	#ifdef CONFIG_88EU_P2P
  1931		case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
  1932			{
  1933				u8 p2p_ps_state = (*(u8 *)val);
  1934				rtl8188e_set_p2p_ps_offload_cmd(Adapter, p2p_ps_state);
  1935			}
  1936			break;
  1937	#endif
  1938		case HW_VAR_INITIAL_GAIN:
  1939			{
  1940				struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
  1941				u32 rx_gain = ((u32 *)(val))[0];
  1942	
  1943				if (rx_gain == 0xff) {/* restore rx gain */
  1944					ODM_Write_DIG(podmpriv, pDigTable->BackupIGValue);
  1945				} else {
  1946					pDigTable->BackupIGValue = pDigTable->CurIGValue;
  1947					ODM_Write_DIG(podmpriv, rx_gain);
  1948				}
  1949			}
  1950			break;
  1951		case HW_VAR_TRIGGER_GPIO_0:
  1952			rtl8192cu_trigger_gpio_0(Adapter);
  1953			break;
  1954		case HW_VAR_RPT_TIMER_SETTING:
  1955			{
  1956				u16 min_rpt_time = (*(u16 *)val);
  1957				ODM_RA_Set_TxRPT_Time(podmpriv, min_rpt_time);
  1958			}
  1959			break;
  1960		case HW_VAR_ANTENNA_DIVERSITY_SELECT:
  1961			{
  1962				u8 Optimum_antenna = (*(u8 *)val);
  1963				u8 Ant;
  1964				/* switch antenna to Optimum_antenna */
  1965				if (haldata->CurAntenna !=  Optimum_antenna) {
  1966					Ant = (Optimum_antenna == 2) ? MAIN_ANT : AUX_ANT;
  1967					ODM_UpdateRxIdleAnt_88E(&haldata->odmpriv, Ant);
  1968	
  1969					haldata->CurAntenna = Optimum_antenna;
  1970				}
  1971			}
  1972			break;
  1973		case HW_VAR_EFUSE_BYTES: /*  To set EFUE total used bytes, added by Roger, 2008.12.22. */
  1974			haldata->EfuseUsedBytes = *((u16 *)val);
  1975			break;
  1976		case HW_VAR_FIFO_CLEARN_UP:
  1977			{
  1978				struct pwrctrl_priv *pwrpriv = &Adapter->pwrctrlpriv;
  1979				u8 trycnt = 100;
  1980	
  1981				/* pause tx */
  1982				rtw_write8(Adapter, REG_TXPAUSE, 0xff);
  1983	
  1984				/* keep sn */
  1985				Adapter->xmitpriv.nqos_ssn = rtw_read16(Adapter, REG_NQOS_SEQ);
  1986	
  1987				if (!pwrpriv->bkeepfwalive) {
  1988					/* RX DMA stop */
  1989					rtw_write32(Adapter, REG_RXPKT_NUM, (rtw_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
  1990					do {
  1991						if (!(rtw_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE))
  1992							break;
  1993					} while (trycnt--);
  1994					if (trycnt == 0)
  1995						DBG_88E("Stop RX DMA failed......\n");
  1996	
  1997					/* RQPN Load 0 */
  1998					rtw_write16(Adapter, REG_RQPN_NPQ, 0x0);
  1999					rtw_write32(Adapter, REG_RQPN, 0x80000000);
  2000					mdelay(10);
  2001				}
  2002			}
  2003			break;
  2004		case HW_VAR_CHECK_TXBUF:
  2005			break;
  2006		case HW_VAR_APFM_ON_MAC:
  2007			haldata->bMacPwrCtrlOn = *val;
  2008			DBG_88E("%s: bMacPwrCtrlOn=%d\n", __func__, haldata->bMacPwrCtrlOn);
  2009			break;
  2010		case HW_VAR_TX_RPT_MAX_MACID:
  2011			{
  2012				u8 maxMacid = *val;
  2013				DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1);
  2014				rtw_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);
  2015			}
  2016			break;
  2017		case HW_VAR_H2C_MEDIA_STATUS_RPT:
  2018			rtl8188e_set_FwMediaStatus_cmd(Adapter, (*(__le16 *)val));
  2019			break;
  2020		case HW_VAR_BCN_VALID:
  2021			/* BCN_VALID, BIT(16) of REG_TDECTRL = BIT(0) of REG_TDECTRL+2, write 1 to clear, Clear by sw */
> 2022			u8 tmp;

2023
2024 error = rtw_read8(Adapter, REG_TDECTRL + 2, &tmp);
2025 if (error)
2026 return;
2027
2028 rtw_write8(Adapter, REG_TDECTRL + 2, tmp | BIT(0));
2029 break;
2030 default:
2031 break;
2032 }
2033

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org