Message ID | 20231117130836.1.I77097aa9ec01aeca1b3c75fde4ba5007a17fdf76@changeid |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:9910:0:b0:403:3b70:6f57 with SMTP id i16csp815018vqn; Fri, 17 Nov 2023 13:11:00 -0800 (PST) X-Google-Smtp-Source: AGHT+IEn+LSCM+A29G+9i80ro7Nuye78mvoYcOp0PTVToC+Uwm3Y1GCz7uaZXLfEDIsjBSNckamj X-Received: by 2002:a17:902:7792:b0:1ce:5f98:1b32 with SMTP id o18-20020a170902779200b001ce5f981b32mr847265pll.61.1700255459752; Fri, 17 Nov 2023 13:10:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700255459; cv=none; d=google.com; s=arc-20160816; b=c8Brm5VfqJR9WHXkackFnVDYFwvKarEcKbeaPDjQYorAdTjj3bhbM1LaVqGF2OOJzb IfV56r8Uv8t5ST12UnIjgHcYxpqaROo7se40zBkNyQf8/Jv7B15VF8xvYSPKzBLigXXs Lf7RJXli6BI5DA6itXhAWXsFuY8HKLS+9ugWf7VSYkJ3HKtOFzwe6SEIuIFvZyfkFlVM XJjRuRTZ8DS6ZYSt7R4h7jF21W5/OxvnekGUj+z1mXqtSoFMkO4+wD1evyhTm93koH0+ W+Nj1CE9K5iX1pIsr2v94BGStLklmc/Rl/xNYW35PuPXZmtIQaUEa6r1h32e56Q49R1N U7Zg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=6wz1t+l8RssdWaevpsmYkaZfUjbmCNYMu71lLo08Sgs=; fh=YpCq/PBTQvS6gw+eWmaXDTpICRmZ9tZKQpE2Dguby3c=; b=dcMeApM7N+LDW4XRXJ8lR77M672jfvpXV4+vKdIenjurFyQCFvFAMhIuh/cdKsHpyS cD/NSIrrfvIJtqS94puP99EhXo5yT565DT/4TW1PcpMCTbqaR6WC5xMe3DEExHlkY1F7 Guyr89GOSMFJDSxi2LTh2ALWJy9xLCizxoNGNM1rxb1LQo2oZkuK741KspweVcarphtD 8QnTkO1DcMavwmVtL+q2I5UxI7yqZ41HzSKPbUeADGGxFSJBfoi8mqF6NjZakcREvH7I ocg3rwX+p4tlhYIiYsLrdbY5dC9L7gY2V7RbMbAD6F3nJkbAEX3tyNKQeyK/G524WA8a rtgg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=kAkHxOwr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id u5-20020a17090341c500b001cc0d2e97f8si2765572ple.575.2023.11.17.13.10.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Nov 2023 13:10:59 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=kAkHxOwr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 8B1E783784A7; Fri, 17 Nov 2023 13:10:51 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346202AbjKQVKZ (ORCPT <rfc822;jaysivo@gmail.com> + 29 others); Fri, 17 Nov 2023 16:10:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235787AbjKQVKS (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 17 Nov 2023 16:10:18 -0500 Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1CDA1732 for <linux-kernel@vger.kernel.org>; Fri, 17 Nov 2023 13:09:57 -0800 (PST) Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-6c115026985so2493391b3a.1 for <linux-kernel@vger.kernel.org>; Fri, 17 Nov 2023 13:09:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1700255397; x=1700860197; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=6wz1t+l8RssdWaevpsmYkaZfUjbmCNYMu71lLo08Sgs=; b=kAkHxOwrS5quIbPQh6wjHSXX9Wot39Bcq6Hp/m+/pqUFUhGnZcRl+7btX1SmFR0D5I FXtC3Gt36Tpr0pbSdj9GU10CilJmHWfjMp0fKpb9IqpC1Rlkmw3iLhfeeXSbNQCkN568 K1hyi32Ruf/h0r0k/6VGfXpiaGAnqDc9ctJAU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700255397; x=1700860197; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=6wz1t+l8RssdWaevpsmYkaZfUjbmCNYMu71lLo08Sgs=; b=nA+tub9S7G4yg2violb5uKcowlg7+CtxfmhcgvonF2KVM/s/FYxwKfEY2FKR7xWL8U PxbyeMnFRSEZJaZx2nWQtFwKrlU4R3zn0btjU1+fhLWULCl/GycPlQNLYrnMdV2cwipL F7+mH0KKdHX7SMGTJ2SBmZ50W9yWbqZaG/Mfqt6i2jNwaDGFgRXpcIPlvuVrMmWlLMjC Wc9gASDXRoinOirnFaOe5pesZC9812tIAr63TKdINeZFBMm9w7FpzlgmNf2bOw87l5nu DMQ9QtIMsjYgSlfSyhb0CWxlHK5DUxzIi3UJy0vJ4QP3LgKW6ixBDhIgLghbRQ2NMAsV eg/Q== X-Gm-Message-State: AOJu0YzWhZNLxZAIdfoX7Y7CQKcIhqMo79mNSnt9qpbDg8spJYnVVrs7 2nu4OCuBWvayXXGaTMMSjCZyPg== X-Received: by 2002:a05:6a20:748e:b0:187:fe09:272a with SMTP id p14-20020a056a20748e00b00187fe09272amr424763pzd.49.1700255396830; Fri, 17 Nov 2023 13:09:56 -0800 (PST) Received: from tictac2.mtv.corp.google.com ([2620:15c:9d:2:b953:95f4:4240:7018]) by smtp.gmail.com with ESMTPSA id h20-20020a056a00219400b006c624e8e7e8sm1780587pfi.83.2023.11.17.13.09.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Nov 2023 13:09:56 -0800 (PST) From: Douglas Anderson <dianders@chromium.org> To: Jakub Kicinski <kuba@kernel.org>, Hayes Wang <hayeswang@realtek.com>, "David S . Miller" <davem@davemloft.net> Cc: Grant Grundler <grundler@chromium.org>, Simon Horman <horms@kernel.org>, Edward Hill <ecgh@chromium.org>, linux-usb@vger.kernel.org, Laura Nao <laura.nao@collabora.com>, Alan Stern <stern@rowland.harvard.edu>, Douglas Anderson <dianders@chromium.org>, =?utf-8?q?Bj=C3=B8rn_Mork?= <bjorn@mork.no>, Eric Dumazet <edumazet@google.com>, Paolo Abeni <pabeni@redhat.com>, linux-kernel@vger.kernel.org, netdev@vger.kernel.org Subject: [PATCH 1/2] r8152: Hold the rtnl_lock for all of reset Date: Fri, 17 Nov 2023 13:08:41 -0800 Message-ID: <20231117130836.1.I77097aa9ec01aeca1b3c75fde4ba5007a17fdf76@changeid> X-Mailer: git-send-email 2.43.0.rc0.421.g78406f8d94-goog MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Fri, 17 Nov 2023 13:10:51 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782847069047472233 X-GMAIL-MSGID: 1782847069047472233 |
Series |
[1/2] r8152: Hold the rtnl_lock for all of reset
|
|
Commit Message
Doug Anderson
Nov. 17, 2023, 9:08 p.m. UTC
As of commit d9962b0d4202 ("r8152: Block future register access if
register access fails") there is a race condition that can happen
between the USB device reset thread and napi_enable() (not) getting
called during rtl8152_open(). Specifically:
* While rtl8152_open() is running we get a register access error
that's _not_ -ENODEV and queue up a USB reset.
* rtl8152_open() exits before calling napi_enable() due to any reason
(including usb_submit_urb() returning an error).
In that case:
* Since the USB reset is perform in a separate thread asynchronously,
it can run at anytime USB device lock is not held - even before
rtl8152_open() has exited with an error and caused __dev_open() to
clear the __LINK_STATE_START bit.
* The rtl8152_pre_reset() will notice that the netif_running() returns
true (since __LINK_STATE_START wasn't cleared) so it won't exit
early.
* rtl8152_pre_reset() will then hang in napi_disable() because
napi_enable() was never called.
We can fix the race by making sure that the r8152 reset routines don't
run at the same time as we're opening the device. Specifically we need
the reset routines in their entirety rely on the return value of
netif_running(). The only way to reliably depend on that is for them
to hold the rntl_lock() mutex for the duration of reset.
Grabbing the rntl_lock() mutex for the duration of reset seems like a
long time, but reset is not expected to be common and the rtnl_lock()
mutex is already held for long durations since the core grabs it
around the open/close calls.
Fixes: d9962b0d4202 ("r8152: Block future register access if register access fails")
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
drivers/net/usb/r8152.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
Comments
On Fri, Nov 17, 2023 at 1:10 PM Douglas Anderson <dianders@chromium.org> wrote: > > As of commit d9962b0d4202 ("r8152: Block future register access if > register access fails") there is a race condition that can happen > between the USB device reset thread and napi_enable() (not) getting > called during rtl8152_open(). Specifically: > * While rtl8152_open() is running we get a register access error > that's _not_ -ENODEV and queue up a USB reset. > * rtl8152_open() exits before calling napi_enable() due to any reason > (including usb_submit_urb() returning an error). > > In that case: > * Since the USB reset is perform in a separate thread asynchronously, > it can run at anytime USB device lock is not held - even before > rtl8152_open() has exited with an error and caused __dev_open() to > clear the __LINK_STATE_START bit. > * The rtl8152_pre_reset() will notice that the netif_running() returns > true (since __LINK_STATE_START wasn't cleared) so it won't exit > early. > * rtl8152_pre_reset() will then hang in napi_disable() because > napi_enable() was never called. > > We can fix the race by making sure that the r8152 reset routines don't > run at the same time as we're opening the device. Specifically we need > the reset routines in their entirety rely on the return value of > netif_running(). The only way to reliably depend on that is for them > to hold the rntl_lock() mutex for the duration of reset. > > Grabbing the rntl_lock() mutex for the duration of reset seems like a > long time, but reset is not expected to be common and the rtnl_lock() > mutex is already held for long durations since the core grabs it > around the open/close calls. > > Fixes: d9962b0d4202 ("r8152: Block future register access if register access fails") > Signed-off-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: Grant Grundler <grundler@chromium.org> BTW, for ChromeOS systems, the outcome of hang in napi_disable() is a "hung task" panic after 120 seconds. Fortunately, the stack trace made it relatively easy (compared to other hung tasks I've looked at) to unravel. Doug gets all the credit for figuring out this solution (using rtnl_lock()). cheers, grant > --- > > drivers/net/usb/r8152.c | 13 +++++++------ > 1 file changed, 7 insertions(+), 6 deletions(-) > > diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c > index 2c5c1e91ded6..d6edf0254599 100644 > --- a/drivers/net/usb/r8152.c > +++ b/drivers/net/usb/r8152.c > @@ -8397,6 +8397,8 @@ static int rtl8152_pre_reset(struct usb_interface *intf) > struct r8152 *tp = usb_get_intfdata(intf); > struct net_device *netdev; > > + rtnl_lock(); > + > if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) > return 0; > > @@ -8428,20 +8430,17 @@ static int rtl8152_post_reset(struct usb_interface *intf) > struct sockaddr sa; > > if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) > - return 0; > + goto exit; > > rtl_set_accessible(tp); > > /* reset the MAC address in case of policy change */ > - if (determine_ethernet_addr(tp, &sa) >= 0) { > - rtnl_lock(); > + if (determine_ethernet_addr(tp, &sa) >= 0) > dev_set_mac_address (tp->netdev, &sa, NULL); > - rtnl_unlock(); > - } > > netdev = tp->netdev; > if (!netif_running(netdev)) > - return 0; > + goto exit; > > set_bit(WORK_ENABLE, &tp->flags); > if (netif_carrier_ok(netdev)) { > @@ -8460,6 +8459,8 @@ static int rtl8152_post_reset(struct usb_interface *intf) > if (!list_empty(&tp->rx_done)) > napi_schedule(&tp->napi); > > +exit: > + rtnl_unlock(); > return 0; > } > > -- > 2.43.0.rc0.421.g78406f8d94-goog >
On Fri, 2023-11-17 at 13:08 -0800, Douglas Anderson wrote: > As of commit d9962b0d4202 ("r8152: Block future register access if > register access fails") there is a race condition that can happen > between the USB device reset thread and napi_enable() (not) getting > called during rtl8152_open(). Specifically: > * While rtl8152_open() is running we get a register access error > that's _not_ -ENODEV and queue up a USB reset. > * rtl8152_open() exits before calling napi_enable() due to any reason > (including usb_submit_urb() returning an error). > > In that case: > * Since the USB reset is perform in a separate thread asynchronously, > it can run at anytime USB device lock is not held - even before > rtl8152_open() has exited with an error and caused __dev_open() to > clear the __LINK_STATE_START bit. > * The rtl8152_pre_reset() will notice that the netif_running() returns > true (since __LINK_STATE_START wasn't cleared) so it won't exit > early. > * rtl8152_pre_reset() will then hang in napi_disable() because > napi_enable() was never called. > > We can fix the race by making sure that the r8152 reset routines don't > run at the same time as we're opening the device. Specifically we need > the reset routines in their entirety rely on the return value of > netif_running(). The only way to reliably depend on that is for them > to hold the rntl_lock() mutex for the duration of reset. Acquiring the rtnl_lock in a callback and releasing it in a different one, with the latter called depending on the configuration, looks fragile and possibly prone to deadlock issues. Have you tested your patch with lockdep enabled? Can you instead acquire the rtnl lock only for pre_reset/post_rest and in rtl8152_open() do something alike: for (i = 0; i < MAX_WAIT; ++i) { if (usb_lock_device_for_reset(udev, NULL)) goto error; wait_again = udev->reset_in_progress; usb_unlock_device(udev); if (!wait_again) break; usleep(1); } if (i == MAX_WAIT) goto error; which should be more polite to other locks? Thanks, Paolo
Hi, On Tue, Nov 21, 2023 at 2:25 AM Paolo Abeni <pabeni@redhat.com> wrote: > > On Fri, 2023-11-17 at 13:08 -0800, Douglas Anderson wrote: > > As of commit d9962b0d4202 ("r8152: Block future register access if > > register access fails") there is a race condition that can happen > > between the USB device reset thread and napi_enable() (not) getting > > called during rtl8152_open(). Specifically: > > * While rtl8152_open() is running we get a register access error > > that's _not_ -ENODEV and queue up a USB reset. > > * rtl8152_open() exits before calling napi_enable() due to any reason > > (including usb_submit_urb() returning an error). > > > > In that case: > > * Since the USB reset is perform in a separate thread asynchronously, > > it can run at anytime USB device lock is not held - even before > > rtl8152_open() has exited with an error and caused __dev_open() to > > clear the __LINK_STATE_START bit. > > * The rtl8152_pre_reset() will notice that the netif_running() returns > > true (since __LINK_STATE_START wasn't cleared) so it won't exit > > early. > > * rtl8152_pre_reset() will then hang in napi_disable() because > > napi_enable() was never called. > > > > We can fix the race by making sure that the r8152 reset routines don't > > run at the same time as we're opening the device. Specifically we need > > the reset routines in their entirety rely on the return value of > > netif_running(). The only way to reliably depend on that is for them > > to hold the rntl_lock() mutex for the duration of reset. > > Acquiring the rtnl_lock in a callback and releasing it in a different > one, with the latter called depending on the configuration, looks > fragile and possibly prone to deadlock issues. Yeah, I debated this as well. I looked through the USB code and I couldn't find any reason that it wouldn't work to hold the lock for the duration. I agree that it's a little more fragile in one sense, but I think it avoids potential races too and that makes it less fragile in a different sense. ;-) > Have you tested your patch with lockdep enabled? Yes, lockdep reported no problems with my patch. Indeed lockdep hints are how I ended up with the current solution. When I originally tried to lock the device in rtl8152_open() then lockdep yelled at me about the AB BA issues between the device lock and the rtnl_lock() mutex which made me realize that grabbing the rtnl_lock() in the reset code was the right solution here. > Can you instead acquire the rtnl lock only for pre_reset/post_rest and > in rtl8152_open() do something alike: > > for (i = 0; i < MAX_WAIT; ++i) { > if (usb_lock_device_for_reset(udev, NULL)) > goto error; > > wait_again = udev->reset_in_progress; > usb_unlock_device(udev); > if (!wait_again) > break; > > usleep(1); > } > if (i == MAX_WAIT) > goto error; > > which should be more polite to other locks? Right, I could add a call to usb_lock_device_for_reset() here. That shouldn't trigger AB BA lockdep splats since it has a timeout. I'm not 100% convinced that it's right, though. ...and I'm fairly certain that if we call it we don't want to call it in a loop. I don't think we should have a loop because usb_lock_device_for_reset() already has a loop in it and I don't think an extra loop will help. I'd imagine that usb_lock_device_for_reset() would usually timeout only if USB reset is currently running and somehow blocked. If pre_reset or post_reset are currently running then they've already got the USB lock (from their caller) and may be blocked waiting for the rtnl_lock. We've already got the rtnl_lock (from our caller) and now we're waiting for the USB lock. In neither case do I think it's a good idea to drop the locks that our caller grabbed for us, so about the best we can do in that case is return an error from r8152_open() after the first timeout. Let's step back and think about why we might want to get the USB lock in the first place. This would only be necessary if we dropped the lock between pre_reset and post_reset, right? ...so we're trying to make sure that we're not trying to open a device while the USB reset code is half executed. I guess the expected order of operations we're trying to protect against would be: 1. rtl8152_close() is called and has a transfer error that queues up a reset. 2. USB reset starts and pre-reset runs. It should be a no-op because netif_running() would return false. 3. rl8152_open() is called and opens the device successfully 4. USB reset runs post-reset, which is no longer the inverse of pre-reset because netif_running() would return true. This would end up with, among other things, an unbalanced napi_enable() count. That feels relatively unlikely to actually hit but it does seem conceivably possible. Thus if we do drop the rtnl_lock between pre-reset and post-reset then I agree we should call usb_lock_device_for_reset(). Probably we need to do that for _both_ rtl8152_open() and rtl8152_close()? We also probably don't need to hold the lock for the whole duration of rtl8152_open() / rtl8152_close(). We can just grab it and release it to make sure that we're not midway through a reset. I guess one sorta odd thing here is that it means that rtl8152_close() could now fail if someone called it at just the right time and we were unable to grab the USB lock. Though it does have an error return, that's not a failure that I'd expect most users to be able to handle terribly well. I guess conceivably we could return -EAGAIN or -EDEADLOCK in this case, but ick... Hopefully the above makes sense. I'd be interested to hear your further thoughts on the issue. I'd still lean towards leaving the code as-is and holding the rtnl_lock across the whole reset, but for all practical purposes I think it would be fine to split it and add usb_lock_device_for_reset() to the rtl8152_open() / rtl8152_close(), since the issues I talk about above seem like they'd need extremely rare timing conditions to hit. -Doug
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2c5c1e91ded6..d6edf0254599 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -8397,6 +8397,8 @@ static int rtl8152_pre_reset(struct usb_interface *intf) struct r8152 *tp = usb_get_intfdata(intf); struct net_device *netdev; + rtnl_lock(); + if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) return 0; @@ -8428,20 +8430,17 @@ static int rtl8152_post_reset(struct usb_interface *intf) struct sockaddr sa; if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) - return 0; + goto exit; rtl_set_accessible(tp); /* reset the MAC address in case of policy change */ - if (determine_ethernet_addr(tp, &sa) >= 0) { - rtnl_lock(); + if (determine_ethernet_addr(tp, &sa) >= 0) dev_set_mac_address (tp->netdev, &sa, NULL); - rtnl_unlock(); - } netdev = tp->netdev; if (!netif_running(netdev)) - return 0; + goto exit; set_bit(WORK_ENABLE, &tp->flags); if (netif_carrier_ok(netdev)) { @@ -8460,6 +8459,8 @@ static int rtl8152_post_reset(struct usb_interface *intf) if (!list_empty(&tp->rx_done)) napi_schedule(&tp->napi); +exit: + rtnl_unlock(); return 0; }