Skip to contentSkip to conversation

staging: r8188eu: Remove _enter/_exit_critical_mutex()

PATCH Superseded Fabio M. De Francesco 3 participants 4 messages Aug 19, 2021 Staging

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 staging: r8188eu: Remove _enter/_exit_critical_mutex()

Remove _enter_critical_mutex() and _exit_critical_mutex(). They are unnecessary wrappers, respectively to mutex_lock_interruptible() and to mutex_unlock(). They also have an odd interface that takes an unused argument named pirqL of type unsigned long. Replace them with the in-kernel API. Ignore return values as it was in the old code.

---

v2: Ignore return values from Mutexes API.

 drivers/staging/r8188eu/core/rtw_mlme_ext.c     |  5 +++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c     |  5 +++--
 drivers/staging/r8188eu/include/osdep_service.h | 13 -------------
 drivers/staging/r8188eu/os_dep/os_intfs.c       |  5 +++--
 4 files changed, 9 insertions(+), 19 deletions(-)
drivers/staging/r8188eu/core/rtw_mlme_ext.c +3 -2
index 5325fe41fbee..9f53cab33333 100644
@@ -4359,7 +4359,8 @@ s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return -1;
 
-	_enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
+		;	/*ignore return value */
 	pxmitpriv->ack_tx = true;
 
 	pmgntframe->ack_report = 1;
@@ -4368,7 +4369,7 @@ s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg
 	}
 
 	pxmitpriv->ack_tx = false;
-	_exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	mutex_unlock(&pxmitpriv->ack_tx_mutex);
 
 	return ret;
 }
drivers/staging/r8188eu/hal/usb_ops_linux.c +3 -2
index 953fa05dc30c..120d6e2c6065 100644
@@ -32,7 +32,8 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata,
 		goto exit;
 	}
 
-	_enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+	if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex))
+		;	/* ignore return value */
 
 	/*  Acquire IO memory for vendorreq */
 	pIo_buf = dvobjpriv->usb_vendor_req_buf;
@@ -96,7 +97,7 @@ static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u16 value, void *pdata,
 			break;
 	}
 release_mutex:
-	_exit_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
+	mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
 exit:
 	return status;
 }
drivers/staging/r8188eu/include/osdep_service.h +0 -13
index 029aa4e92c9b..bb92b9d74bd7 100644
@@ -56,19 +56,6 @@ static inline struct list_head *get_list_head(struct __queue *queue)
 	return (&(queue->queue));
 }
 
-static inline int _enter_critical_mutex(struct mutex *pmutex, unsigned long *pirqL)
-{
-	int ret;
-
-	ret = mutex_lock_interruptible(pmutex);
-	return ret;
-}
-
-static inline void _exit_critical_mutex(struct mutex *pmutex, unsigned long *pirqL)
-{
-		mutex_unlock(pmutex);
-}
-
 static inline void rtw_list_delete(struct list_head *plist)
 {
 	list_del_init(plist);
drivers/staging/r8188eu/os_dep/os_intfs.c +3 -2
index 1aa65925e1da..3823042256a6 100644
@@ -1065,9 +1065,10 @@ int netdev_open(struct net_device *pnetdev)
 	int ret;
 	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
 
-	_enter_critical_mutex(padapter->hw_init_mutex, NULL);
+	if (mutex_lock_interruptible(padapter->hw_init_mutex))
+		;	/* ignore return value */
 	ret = _netdev_open(pnetdev);
-	_exit_critical_mutex(padapter->hw_init_mutex, NULL);
+	mutex_unlock(padapter->hw_init_mutex);
 	return ret;
 }
 
Signature · 1 line
2.32.0
#1 lore raw
Quoted 23 lines · Fabio M. De Francesco

Remove _enter_critical_mutex() and _exit_critical_mutex(). They are unnecessary wrappers, respectively to mutex_lock_interruptible() and to mutex_unlock(). They also have an odd interface that takes an unused argument named pirqL of type unsigned long. Replace them with the in-kernel API. Ignore return values as it was in the old code.

---

v2: Ignore return values from Mutexes API.

 drivers/staging/r8188eu/core/rtw_mlme_ext.c     |  5 +++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c     |  5 +++--
 drivers/staging/r8188eu/include/osdep_service.h | 13 -------------
 drivers/staging/r8188eu/os_dep/os_intfs.c       |  5 +++--
 4 files changed, 9 insertions(+), 19 deletions(-)
drivers/staging/r8188eu/core/rtw_mlme_ext.c +0 -0
index 5325fe41fbee..9f53cab33333 100644

drivers/staging/r8188eu/core/rtw_mlme_ext.c s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg · line 4363

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_mlme_ext.c +2 -1
@@ -4359,7 +4359,8 @@ s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return -1;
 
-	_enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
+		;	/*ignore return value */

Ick, no. (not to mention the wrong comment style...)

If this really is "criticial", why can it be interrupted?

The existing code is such that the code can be interrupted, but if it fails, the lock is not gotten, and the CODE CONTINUES AS IF IT IS OK!

So either this is never interruptable (my guess, one almost never needs interruptable locks in a driver) and should just do a normal mutex lock, or the code is totally broken and the locking should be revisited entirely.

But a "blind" change like this is not good, let's get it right...

thanks,

greg k-h

#2 lore raw
Quoted 33 lines · CEST Greg Kroah-Hartman
Quoted 23 lines · Fabio M. De Francesco

Remove _enter_critical_mutex() and _exit_critical_mutex(). They are unnecessary wrappers, respectively to mutex_lock_interruptible() and to mutex_unlock(). They also have an odd interface that takes an unused argument named pirqL of type unsigned long. Replace them with the in-kernel API. Ignore return values as it was in the old code.

---

v2: Ignore return values from Mutexes API.

 drivers/staging/r8188eu/core/rtw_mlme_ext.c     |  5 +++--
 drivers/staging/r8188eu/hal/usb_ops_linux.c     |  5 +++--
 drivers/staging/r8188eu/include/osdep_service.h | 13 -------------
 drivers/staging/r8188eu/os_dep/os_intfs.c       |  5 +++--
 4 files changed, 9 insertions(+), 19 deletions(-)
drivers/staging/r8188eu/core/rtw_mlme_ext.c +0 -0
index 5325fe41fbee..9f53cab33333 100644

drivers/staging/r8188eu/core/rtw_mlme_ext.c s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg · line 4363

Quoted 6 lines
drivers/staging/r8188eu/core/rtw_mlme_ext.c +2 -1
@@ -4359,7 +4359,8 @@ s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmg
 	if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
 		return -1;
 
-	_enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
+		;	/*ignore return value */

Ick, no. (not to mention the wrong comment style...)

Quoted 4 lines

If this really is "criticial", why can it be interrupted?

The existing code is such that the code can be interrupted, but if it fails, the lock is not gotten, and the CODE CONTINUES AS IF IT IS OK!

This was perfectly clear. The old code ignored -EINTR and, in case when blocking to wait for the lock to become available is interrupted (although I really don't know how - a signal to a driver? I guess it cannot happen) it continues to execute in the critical region so leading to potential race conditions.

This is what I get and I guess I'm not too far from the truth... Did I get it right?

Quoted 2 lines

So either this is never interruptable (my guess, one almost never needs interruptable locks in a driver)

This is what I think, why interruptible locks in a driver? I suppose that they should only be used when the kernel executes on behalf of a process.

Quoted 3 lines

and should just do a normal mutex lock,
or the code is totally broken and the locking should be revisited entirely.

My guess is that the code that is waiting to acquire a lock could *really* be interrupted should manage that interruption without falling blindly in the critical region and we have two ways to do that:

1) return -EINTR to the caller which should manage that error by retrying the acquisition, or

2) retry in a loop inside the callee, avoiding to proceed to the critical section without an acquired mutex.

A third option is using mutex_lock() (uninterruptible), which I would prefer if I were absolutely sure that nothing could interrupt waiting for acquiring the lock.

I have to look at how other drivers manage similar cases, although I'm pretty convinced that a simple mutex_lock() should be fine here.

Thanks,

Fabio

Quoted 1 line

But a "blind" change like this is not good, let's get it right...

I agree, let me take some time to investigate what are the best practices that the kernel implements in cases like this. What I'm sure at the moment is that the old code, as-is, is broken.

Thanks,

Fabio

Quoted 4 lines

thanks,

greg k-h

#3 lore raw
In reply to Fabio M. De Francesco
Thank you for the patch! Perhaps something to improve:

Hi "Fabio,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on staging/staging-testing]

url:    https://github.com/0day-ci/linux/commits/Fabio-M-De-Francesco/staging-r8188eu-Remove-_enter-_exit_critical_mutex/20210819-205259
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 093991aaadf0fbb34184fa37a46e7a157da3f386
config: m68k-allmodconfig (attached as .config)
compiler: m68k-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/be2317351161f572a68f71544046d8491856818f
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Fabio-M-De-Francesco/staging-r8188eu-Remove-_enter-_exit_critical_mutex/20210819-205259 git checkout be2317351161f572a68f71544046d8491856818f
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=m68k

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

All warnings (new ones prefixed by >>):

drivers/staging/r8188eu/core/rtw_mlme_ext.c: In function 'dump_mgntframe_and_wait_ack':

>> drivers/staging/r8188eu/core/rtw_mlme_ext.c:4363:17: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
    4363 |                 ;       /*ignore return value */
         |                 ^
--
   drivers/staging/r8188eu/hal/usb_ops_linux.c: In function 'usbctrl_vendorreq':
>> drivers/staging/r8188eu/hal/usb_ops_linux.c:36:17: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
      36 |                 ;       /* ignore return value */
         |                 ^
--
   drivers/staging/r8188eu/os_dep/os_intfs.c: In function 'netdev_open':
>> drivers/staging/r8188eu/os_dep/os_intfs.c:1069:17: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
    1069 |                 ;       /* ignore return value */
         |                 ^

vim +/if +4363 drivers/staging/r8188eu/core/rtw_mlme_ext.c

4352
4353 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
4354 {
4355 s32 ret = _FAIL;
4356 u32 timeout_ms = 500;/* 500ms */
4357 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4358
4359 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4360 return -1;
4361
4362 if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))

> 4363			;	/*ignore return value */

4364 pxmitpriv->ack_tx = true;
4365
4366 pmgntframe->ack_report = 1;
4367 if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
4368 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
4369 }
4370
4371 pxmitpriv->ack_tx = false;
4372 mutex_unlock(&pxmitpriv->ack_tx_mutex);
4373
4374 return ret;
4375 }
4376

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