[PATCH net-next] r8152: use GFP_NOIO during system suspend

Chih Kai Hsu <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb
Message-ID <[email protected]>
During system suspend, memory allocation with GFP_KERNEL can block
waiting for I/O to complete. If that I/O depends on a device that is
itself suspended, a deadlock results.

Introduce RTL8152_SYSTEM_SUSPEND flag to track when the driver is
operating in the system suspend/resume context. Set the flag at the
start of rtl8152_system_suspend() and clear it at the end of
rtl8152_system_resume(), following the same pattern used by
SELECTIVE_SUSPEND for runtime suspend.

In get_registers() and set_registers(), select GFP_NOIO when the flag
is set so that the kmalloc and kmemdup calls in those paths do not
trigger I/O reclaim.

Signed-off-by: Chih Kai Hsu <[email protected]>
---
 drivers/net/usb/r8152.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index f61686433031..57d04af6368c 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -792,6 +792,7 @@ enum rtl8152_flags {
 	IN_PRE_RESET,
 	PROBED_WITH_NO_ERRORS,
 	PROBE_SHOULD_RETRY,
+	RTL8152_SYSTEM_SUSPEND,
 };
 
 #define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB		0x721e
@@ -1370,9 +1371,12 @@ static
 int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
 {
 	int ret;
+	gfp_t gfp;
 	void *tmp;
 
-	tmp = kmalloc(size, GFP_KERNEL);
+	gfp = test_bit(RTL8152_SYSTEM_SUSPEND, &tp->flags) ? GFP_NOIO :
+							     GFP_KERNEL;
+	tmp = kmalloc(size, gfp);
 	if (!tmp)
 		return -ENOMEM;
 
@@ -1394,9 +1398,12 @@ static
 int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
 {
 	int ret;
+	gfp_t gfp;
 	void *tmp;
 
-	tmp = kmemdup(data, size, GFP_KERNEL);
+	gfp = test_bit(RTL8152_SYSTEM_SUSPEND, &tp->flags) ? GFP_NOIO :
+							     GFP_KERNEL;
+	tmp = kmemdup(data, size, gfp);
 	if (!tmp)
 		return -ENOMEM;
 
@@ -8693,6 +8700,9 @@ static int rtl8152_system_resume(struct r8152 *tp)
 		usb_submit_urb(tp->intr_urb, GFP_NOIO);
 	}
 
+	clear_bit(RTL8152_SYSTEM_SUSPEND, &tp->flags);
+	smp_mb__after_atomic();
+
 	return 0;
 }
 
@@ -8758,6 +8768,9 @@ static int rtl8152_system_suspend(struct r8152 *tp)
 {
 	struct net_device *netdev = tp->netdev;
 
+	set_bit(RTL8152_SYSTEM_SUSPEND, &tp->flags);
+	smp_mb__after_atomic();
+
 	netif_device_detach(netdev);
 
 	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.