linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Stern <stern@rowland.harvard.edu>
To: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Oliver Neukum <oneukum@suse.com>,
	Marco Crivellari <marco.crivellari@suse.com>,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	Tejun Heo <tj@kernel.org>, Lai Jiangshan <jiangshanlai@gmail.com>,
	Frederic Weisbecker <frederic@kernel.org>,
	Michal Hocko <mhocko@suse.com>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Petko Manolov <petkan@nucleusys.com>,
	linux-usb@vger.kernel.org
Subject: Re: [PATCH v3 net-next 5/6] net: usb: pegasus: Move long delayed work on system_dfl_long_wq
Date: Sat, 5 Sep 2026 12:33:07 -0400	[thread overview]
Message-ID: <b6e6e8d0-0888-4bbc-85b8-ca3bdac88398@rowland.harvard.edu> (raw)
In-Reply-To: <20260905150450.2hrac_GV@linutronix.de>

On Sat, Sep 05, 2026 at 05:04:50PM +0200, Sebastian Andrzej Siewior wrote:
> On 2026-08-28 10:10:01 [-0400], Alan Stern wrote:
> > > While this does make sense I don't see how this is related to this
> > > patch. The pegasus driver uses `system_long_wq'. This is a system wide
> > > workqueue_struct and is not limited to USB or this driver.
> > > This workqueue is per-CPU meaning if you enqueue the work item on CPU3
> > > it will be executed on CPU3. However pegasus uses a delayed work item
> > > and the timer can fire on any CPU so even if it is enqueued on CPU3 it
> > > could be executed on CPU1.
> > 
> > It doesn't matter what CPU the work item runs on.  Here's the deadlock 
> > sequence, in brief:
> > 
> > 	USB device reset cannot proceed until network interface's
> > 	->pre_reset() method returns.
> > 
> > 	The ->pre_reset() method cannot return until its call to
> > 	flush_workqueue() returns.
> > 
> > 	flush_workqueue() cannot return until the already executing
> > 	work item finishes.
> 
> Not sure where you pointing at but you have an unordered workqueue (such
> as system_long_wq/ system_dfl_long_wq then you can have more than one
> work item executed in parallel. One item does not stall the other so you
> can flush your work item (waiting for it's completion) without having all
> other work item completed.
> There is no need to flush the workqueue, that would force _all_ work
> item to complete. Flushing a workqueue would make sense if you have your
> own and you want to ensure that _all_ work items, that has been
> enqueued, did complete and you don't want to check them one by one.
> 
> To illustrate your point, the  example would translate to something like
> the following:
> 
> | static struct work_struct test_worker_busy;
> | static struct work_struct test_worker_reg;
> |  
> | static void test_worker_complete_fn(struct work_struct *work)
> | {
> |         int count = 0;
> |         while (1) {
> |                 ssleep(1);
> |                 count++;
> |                 if (count > 10)
> |                         break;
> |         }
> |         pr_err("%s()\n leaving", __func__);
> | }
> |  
> | static void test_worker_busy_fn(struct work_struct *work)
> | {
> |         while (1) {
> |                 ssleep(1);
> |                 pr_err("%s()\n", __func__);
> |         }
> | }
> |  
> | static void the_workers(void)
> | {
> |         INIT_WORK(&test_worker_busy, test_worker_busy_fn);
> |         INIT_WORK(&test_worker_reg, test_worker_complete_fn);
> |  
> |         queue_work(system_long_wq, &test_worker_busy);
> |         ssleep(1);
> |         queue_work(system_long_wq, &test_worker_reg);
> |         pr_err("%s() starting...\n", __func__);
> |         ssleep(1);
> |         pr_err("%s() cancel\n", __func__);
> |         flush_work(&test_worker_reg);
> |         pr_err("%s() moving on\n", __func__);
> | }
> 
> which leads to:
> 
> | [    4.136593] the_workers() starting...
> | [    4.137007] test_worker_busy_fn()
> | [    5.161198] the_workers() cancel
> | [    5.164832] test_worker_busy_fn()
> | [    6.184710] test_worker_busy_fn()
> | [    7.208525] test_worker_busy_fn()
> | [    8.232754] test_worker_busy_fn()
> | [    9.256522] test_worker_busy_fn()
> | [   10.280716] test_worker_busy_fn()
> | [   11.304523] test_worker_busy_fn()
> | [   12.328671] test_worker_busy_fn()
> | [   13.352517] test_worker_busy_fn()
> | [   14.376842] test_worker_busy_fn()
> | [   15.400539] test_worker_busy_fn()
> | [   15.402676] test_worker_complete_fn()
> | [   15.403290] the_workers() moving on
> | [   16.424483] test_worker_busy_fn()
> | [   17.448524] test_worker_busy_fn()
> 
> which means the test_worker_reg work item completed despite the fact
> that test_worker_busy remained busy.
> 
> Of course flushing the workqueue system_long_wq (via flush_workqueue())
> would stall but also raise a warning…
> 
> > 	The work item cannot finish until its kmalloc() call returns.
> > 
> > 	kmalloc() won't return until the kernel can free up memory by 
> > 	writing some pages to the swap partition.
> > 
> > 	The write to the swap partition cannot take place until the
> > 	usb_storage/uas driver carries it out.
> > 
> > 	usb_storage/uas cannot do anything until the USB device reset
> > 	is finished.
> 
> as shown, this is not a concern.
> 
> > > Therefore the suggested change system_long_wq -> system_dfl_long_wq
> > > should not make a difference here: it is a different workqueue and it is
> > > unbound (instead of per-CPU) but given the usage it is unchanged but
> > > more obvious. Also its usage recommendations (use this for long running
> > > items) is the same.
> > > 
> > > The plan is remove system_long_wq from the tree.
> > 
> > The point Oliver was making is that the driver shouldn't be using a 
> > general-purpose workqueue at all.  Switching from one general-purpose 
> > workqueue to another ignores this point; it's not the right thing to do.
> 
> Still the wrong thing to do? The driver should do either flush_work() or
> cancel_work_sync() (not flush_workqueue()).

I think we're in agreement.  If the driver relies on calling 
flush_workqueue(), it should not use a general-purpose workqueue.  
However, flush_work() or cancel_work_sync() is okay on an unordered 
general-purpose workqueue.

If Oliver still has any objections, he can raise them.

Alan Stern

  reply	other threads:[~2026-09-05 16:33 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260720100902.155605-1-marco.crivellari@suse.com>
2026-07-20 10:08 ` [PATCH v3 net-next 5/6] net: usb: pegasus: Move long delayed work on system_dfl_long_wq Marco Crivellari
2026-07-22  8:29   ` Oliver Neukum
2026-08-25 15:18     ` Sebastian Andrzej Siewior
2026-08-27 16:01       ` Alan Stern
2026-08-28  9:43         ` Sebastian Andrzej Siewior
2026-08-28 14:10           ` Alan Stern
2026-09-04 15:01             ` Petko Manolov
2026-09-05 15:04             ` Sebastian Andrzej Siewior
2026-09-05 16:33               ` Alan Stern [this message]
2026-09-06  8:08                 ` Petko Manolov
2026-09-07  9:12                 ` Sebastian Andrzej Siewior
2026-07-20 10:08 ` [PATCH v3 net-next 6/6] net: usb: r8152: " Marco Crivellari

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b6e6e8d0-0888-4bbc-85b8-ca3bdac88398@rowland.harvard.edu \
    --to=stern@rowland.harvard.edu \
    --cc=andrew+netdev@lunn.ch \
    --cc=bigeasy@linutronix.de \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=frederic@kernel.org \
    --cc=jiangshanlai@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=marco.crivellari@suse.com \
    --cc=mhocko@suse.com \
    --cc=netdev@vger.kernel.org \
    --cc=oneukum@suse.com \
    --cc=pabeni@redhat.com \
    --cc=petkan@nucleusys.com \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).