drivers/usb/core/offload.c | 92 +++++++++++++++++++++----------- drivers/usb/host/xhci-sideband.c | 48 +++++++++++------ include/linux/usb.h | 6 +++ 3 files changed, 100 insertions(+), 46 deletions(-)
When a USB device is disconnected or a driver is unbound, the USB core
invokes the driver's disconnect callback while holding the udev device
lock. If the driver calls xhci_sideband_unregister(), it eventually
reaches usb_offload_put(), which attempts to acquire the same udev
lock, resulting in a self-deadlock.
Introduce lockless variants __usb_offload_get() and __usb_offload_put()
to allow modifying the offload usage count when the device lock is
already held. These helpers use device_lock_assert() to ensure callers
meet the locking requirements.
Update the xHCI sideband implementation to use these lockless variants
in the unregister and interrupter removal paths. For public sideband
APIs that can be called from other contexts, wrap the calls with
explicit udev locking to maintain synchronization.
Cc: stable@vger.kernel.org
Fixes: ef82a4803aab ("xhci: sideband: add api to trace sideband usage")
Signed-off-by: Guan-Yu Lin <guanyulin@google.com>
---
Hi Maintainers,
In the current implementation, xhci_sideband_unregister() is only invoked
when a driver manages a USB interface via snd_usb_platform_ops callbacks
(.connect_cb and .disconnect_cb). In these contexts, the parent USB
device lock is already held by the USB core. However, the original design
of usb_offload_put() attempts to re-acquire the same USB device lock,
leading to a recursive locking scenario.
This patch resolves the issue by:
1. Refactoring Lock Ownership: Shifting lock acquisition responsibility
to the upper-level USB driver. This ensures usb_offload_put() can be
safely called from contexts where the lock is already held.
2. Standardizing the Lock Hierarchy: To prevent potential ABBA deadlocks,
the locking sequence is unified across the driver. The functions
xhci_sideband_create_interrupter() and xhci_sideband_remove_interrupter()
have been updated to strictly follow the same hierarchy.
---
drivers/usb/core/offload.c | 92 +++++++++++++++++++++-----------
drivers/usb/host/xhci-sideband.c | 48 +++++++++++------
include/linux/usb.h | 6 +++
3 files changed, 100 insertions(+), 46 deletions(-)
diff --git a/drivers/usb/core/offload.c b/drivers/usb/core/offload.c
index 7c699f1b8d2b..bc5f337fb355 100644
--- a/drivers/usb/core/offload.c
+++ b/drivers/usb/core/offload.c
@@ -13,44 +13,59 @@
#include "usb.h"
/**
- * usb_offload_get - increment the offload_usage of a USB device
+ * __usb_offload_get - increment the offload_usage of a USB device
* @udev: the USB device to increment its offload_usage
*
- * Incrementing the offload_usage of a usb_device indicates that offload is
- * enabled on this usb_device; that is, another entity is actively handling USB
- * transfers. This information allows the USB driver to adjust its power
- * management policy based on offload activity.
+ * This is the lockless version of usb_offload_get. The caller must hold
+ * @udev's device lock.
*
* Return: 0 on success. A negative error code otherwise.
*/
-int usb_offload_get(struct usb_device *udev)
+int __usb_offload_get(struct usb_device *udev)
{
int ret;
- usb_lock_device(udev);
- if (udev->state == USB_STATE_NOTATTACHED) {
- usb_unlock_device(udev);
+ device_lock_assert(&udev->dev);
+
+ if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
- }
if (udev->state == USB_STATE_SUSPENDED ||
- udev->offload_at_suspend) {
- usb_unlock_device(udev);
+ udev->offload_at_suspend)
return -EBUSY;
- }
/*
* offload_usage could only be modified when the device is active, since
* it will alter the suspend flow of the device.
*/
ret = usb_autoresume_device(udev);
- if (ret < 0) {
- usb_unlock_device(udev);
+ if (ret < 0)
return ret;
- }
udev->offload_usage++;
usb_autosuspend_device(udev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__usb_offload_get);
+
+/**
+ * usb_offload_get - increment the offload_usage of a USB device
+ * @udev: the USB device to increment its offload_usage
+ *
+ * Incrementing the offload_usage of a usb_device indicates that offload is
+ * enabled on this usb_device; that is, another entity is actively handling USB
+ * transfers. This information allows the USB driver to adjust its power
+ * management policy based on offload activity.
+ *
+ * Return: 0 on success. A negative error code otherwise.
+ */
+int usb_offload_get(struct usb_device *udev)
+{
+ int ret;
+
+ usb_lock_device(udev);
+ ret = __usb_offload_get(udev);
usb_unlock_device(udev);
return ret;
@@ -58,45 +73,60 @@ int usb_offload_get(struct usb_device *udev)
EXPORT_SYMBOL_GPL(usb_offload_get);
/**
- * usb_offload_put - drop the offload_usage of a USB device
+ * __usb_offload_put - drop the offload_usage of a USB device
* @udev: the USB device to drop its offload_usage
*
- * The inverse operation of usb_offload_get, which drops the offload_usage of
- * a USB device. This information allows the USB driver to adjust its power
- * management policy based on offload activity.
+ * This is the lockless version of usb_offload_put. The caller must hold
+ * @udev's device lock.
*
* Return: 0 on success. A negative error code otherwise.
*/
-int usb_offload_put(struct usb_device *udev)
+int __usb_offload_put(struct usb_device *udev)
{
int ret;
- usb_lock_device(udev);
- if (udev->state == USB_STATE_NOTATTACHED) {
- usb_unlock_device(udev);
+ device_lock_assert(&udev->dev);
+
+ if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
- }
if (udev->state == USB_STATE_SUSPENDED ||
- udev->offload_at_suspend) {
- usb_unlock_device(udev);
+ udev->offload_at_suspend)
return -EBUSY;
- }
/*
* offload_usage could only be modified when the device is active, since
* it will alter the suspend flow of the device.
*/
ret = usb_autoresume_device(udev);
- if (ret < 0) {
- usb_unlock_device(udev);
+ if (ret < 0)
return ret;
- }
/* Drop the count when it wasn't 0, ignore the operation otherwise. */
if (udev->offload_usage)
udev->offload_usage--;
usb_autosuspend_device(udev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__usb_offload_put);
+
+/**
+ * usb_offload_put - drop the offload_usage of a USB device
+ * @udev: the USB device to drop its offload_usage
+ *
+ * The inverse operation of usb_offload_get, which drops the offload_usage of
+ * a USB device. This information allows the USB driver to adjust its power
+ * management policy based on offload activity.
+ *
+ * Return: 0 on success. A negative error code otherwise.
+ */
+int usb_offload_put(struct usb_device *udev)
+{
+ int ret;
+
+ usb_lock_device(udev);
+ ret = __usb_offload_put(udev);
usb_unlock_device(udev);
return ret;
diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c
index 2bd77255032b..c37c3f3adf4a 100644
--- a/drivers/usb/host/xhci-sideband.c
+++ b/drivers/usb/host/xhci-sideband.c
@@ -89,7 +89,7 @@ __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *e
sb->eps[ep->ep_index] = NULL;
}
-/* Caller must hold sb->mutex */
+/* Caller must hold sb->mutex and udev device lock */
static void
__xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
{
@@ -102,10 +102,10 @@ __xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir);
sb->ir = NULL;
- udev = sb->vdev->udev;
- if (udev->state != USB_STATE_NOTATTACHED)
- usb_offload_put(udev);
+ udev = interface_to_usbdev(sb->intf);
+ device_lock_assert(&udev->dev);
+ __usb_offload_put(udev);
}
/* sideband api functions */
@@ -334,25 +334,36 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg,
if (!sb || !sb->xhci)
return -ENODEV;
- guard(mutex)(&sb->mutex);
+ udev = interface_to_usbdev(sb->intf);
+ usb_lock_device(udev);
+ mutex_lock(&sb->mutex);
- if (!sb->vdev)
- return -ENODEV;
+ if (!sb->vdev) {
+ ret = -ENODEV;
+ goto unlock;
+ }
- if (sb->ir)
- return -EBUSY;
+ if (sb->ir) {
+ ret = -EBUSY;
+ goto unlock;
+ }
sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci),
num_seg, imod_interval,
intr_num);
- if (!sb->ir)
- return -ENOMEM;
+ if (!sb->ir) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
- udev = sb->vdev->udev;
- ret = usb_offload_get(udev);
+ ret = __usb_offload_get(udev);
sb->ir->ip_autoclear = ip_autoclear;
+unlock:
+ mutex_unlock(&sb->mutex);
+ usb_unlock_device(udev);
+
return ret;
}
EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter);
@@ -367,12 +378,19 @@ EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter);
void
xhci_sideband_remove_interrupter(struct xhci_sideband *sb)
{
- if (!sb)
+ struct usb_device *udev;
+
+ if (!sb || !sb->vdev)
return;
- guard(mutex)(&sb->mutex);
+ udev = interface_to_usbdev(sb->intf);
+ usb_lock_device(udev);
+ mutex_lock(&sb->mutex);
__xhci_sideband_remove_interrupter(sb);
+
+ mutex_unlock(&sb->mutex);
+ usb_unlock_device(udev);
}
EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index fbfcc70b07fb..19c84c05f376 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -846,11 +846,17 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
#endif
#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND)
+int __usb_offload_get(struct usb_device *udev);
+int __usb_offload_put(struct usb_device *udev);
int usb_offload_get(struct usb_device *udev);
int usb_offload_put(struct usb_device *udev);
bool usb_offload_check(struct usb_device *udev);
#else
+static inline int __usb_offload_get(struct usb_device *udev)
+{ return 0; }
+static inline int __usb_offload_put(struct usb_device *udev)
+{ return 0; }
static inline int usb_offload_get(struct usb_device *udev)
{ return 0; }
static inline int usb_offload_put(struct usb_device *udev)
--
2.53.0.rc1.225.gd81095ad13-goog
On Fri, Jan 30, 2026 at 07:47:46AM +0000, Guan-Yu Lin wrote: > When a USB device is disconnected or a driver is unbound, the USB core > invokes the driver's disconnect callback while holding the udev device > lock. If the driver calls xhci_sideband_unregister(), it eventually > reaches usb_offload_put(), which attempts to acquire the same udev > lock, resulting in a self-deadlock. > > Introduce lockless variants __usb_offload_get() and __usb_offload_put() > to allow modifying the offload usage count when the device lock is > already held. These helpers use device_lock_assert() to ensure callers > meet the locking requirements. Ugh. Didn't I warn about this when the original functions were added? Adding functions with __ is a mess, please make these names, if you _REALLY_ need them, obvious that this is a no lock function. And now that you added the lockless functions, are there any in-kernel users of the locked versions? At a quick glance I didn't see them, did I miss it somewhere? thanks, greg k-h
On Sat, Jan 31, 2026 at 8:15 PM Greg KH <gregkh@linuxfoundation.org> wrote: > > On Fri, Jan 30, 2026 at 07:47:46AM +0000, Guan-Yu Lin wrote: > > When a USB device is disconnected or a driver is unbound, the USB core > > invokes the driver's disconnect callback while holding the udev device > > lock. If the driver calls xhci_sideband_unregister(), it eventually > > reaches usb_offload_put(), which attempts to acquire the same udev > > lock, resulting in a self-deadlock. > > > > Introduce lockless variants __usb_offload_get() and __usb_offload_put() > > to allow modifying the offload usage count when the device lock is > > already held. These helpers use device_lock_assert() to ensure callers > > meet the locking requirements. > > Ugh. Didn't I warn about this when the original functions were added? > > Adding functions with __ is a mess, please make these names, if you > _REALLY_ need them, obvious that this is a no lock function. > > And now that you added the lockless functions, are there any in-kernel > users of the locked versions? At a quick glance I didn't see them, did > I miss it somewhere? > > thanks, > > greg k-h Hi Greg, You are right; xhci-sideband.c is the only in-kernel user of the locked versions. I will rename the __ functions to usb_offload_* and remove the locked variants in the next version to clean up the API. Regarding the deadlock fix itself, we have analyzed two potential solutions. The core issue is that xhci_sideband_unregister() (and xhci_sideband_remove_interrupter()) needs to decrement the offload usage count (which requires the USB device lock), but it is called from the disconnect path where that lock is already held. Option A: Fix the Callers of xhci_sideband functions In this approach, we keep the usb_offload calls inside the xhci_sideband functions but replace the internal usb_lock_device() with device_lock_assert(). We then update callers in qc_audio_offload.c to explicitly acquire the lock. This ensures the offload count remains tightly coupled with the interrupter's lifecycle, though it effectively changes the API contract: calling xHCI sideband functions now requires holding the USB device lock. Option B: Decouple usb_offload functions from xhci_sideband functions In this approach, we strip the usb_offload calls out of xhci_sideband functions entirely. The client driver (qc_audio_offload) becomes responsible for the full transaction: acquiring the lock, managing usb_offload_get/put(), and creating/removing the interrupter. This restores clean encapsulation (xHCI functions only handle hardware), but it places the burden on the client driver to correctly balance the usb_offload calls. I lean towards Option A to ensure the offload count implies an active interrupter by design, but please let me know if you prefer the cleaner separation of Option B. Regards, Guan-Yu
On 2/2/26 12:03, Guan-Yu Lin wrote:
> On Sat, Jan 31, 2026 at 8:15 PM Greg KH <gregkh@linuxfoundation.org> wrote:
>>
>> On Fri, Jan 30, 2026 at 07:47:46AM +0000, Guan-Yu Lin wrote:
>>> When a USB device is disconnected or a driver is unbound, the USB core
>>> invokes the driver's disconnect callback while holding the udev device
>>> lock. If the driver calls xhci_sideband_unregister(), it eventually
>>> reaches usb_offload_put(), which attempts to acquire the same udev
>>> lock, resulting in a self-deadlock.
>>>
>>> Introduce lockless variants __usb_offload_get() and __usb_offload_put()
>>> to allow modifying the offload usage count when the device lock is
>>> already held. These helpers use device_lock_assert() to ensure callers
>>> meet the locking requirements.
>>
>> Ugh. Didn't I warn about this when the original functions were added?
>>
>> Adding functions with __ is a mess, please make these names, if you
>> _REALLY_ need them, obvious that this is a no lock function.
>>
>> And now that you added the lockless functions, are there any in-kernel
>> users of the locked versions? At a quick glance I didn't see them, did
>> I miss it somewhere?
>>
>> thanks,
>>
>> greg k-h
>
> Hi Greg,
>
> You are right; xhci-sideband.c is the only in-kernel user of the
> locked versions. I will rename the __ functions to usb_offload_* and
> remove the locked variants in the next version to clean up the API.
>
> Regarding the deadlock fix itself, we have analyzed two potential
> solutions. The core issue is that xhci_sideband_unregister() (and
> xhci_sideband_remove_interrupter()) needs to decrement the offload
> usage count (which requires the USB device lock), but it is called
> from the disconnect path where that lock is already held.
>
> Option A: Fix the Callers of xhci_sideband functions
> In this approach, we keep the usb_offload calls inside the
> xhci_sideband functions but replace the internal usb_lock_device()
> with device_lock_assert(). We then update callers in
> qc_audio_offload.c to explicitly acquire the lock.
> This ensures the offload count remains tightly coupled with the
> interrupter's lifecycle, though it effectively changes the API
> contract: calling xHCI sideband functions now requires holding the USB
> device lock.
>
> Option B: Decouple usb_offload functions from xhci_sideband functions
> In this approach, we strip the usb_offload calls out of xhci_sideband
> functions entirely. The client driver (qc_audio_offload) becomes
> responsible for the full transaction: acquiring the lock, managing
> usb_offload_get/put(), and creating/removing the interrupter. This
> restores clean encapsulation (xHCI functions only handle hardware),
> but it places the burden on the client driver to correctly balance the
> usb_offload calls.
>
> I lean towards Option A to ensure the offload count implies an active
> interrupter by design, but please let me know if you prefer the
> cleaner separation of Option B.
I would prefer option B
Decouple the offload from sideband.
The secondary interrupter in sideband was specifically createad for
qc_audio_offload.
Vendors using the xHCI hardware Audio sideband Capability (xHCI 7.9)
won't use a secondary interrupter, but might sill want to prevent suspending
the device. So it shuold be better to make this decision in the class driver.
The offload count shoudn't be that complicated. Isn't it binary at the moment?
We don't allow more than one sideband per device, and it can only have one
interrupter.
I unfortunately couldn't participate in the review and development of
drivers/usb/core/offload.c, but my original idea before it was implemented
was to keep usb core out of sideband as much as possible as its not really
a part of usb specification.
This is also why I added the sideband pointer to struct xhci_virt_device.
It allows us to figure out if a device is dedicated for sideband use.
so xhci_sideband_check() could be something like
bool xhci_sideband_check(struct xhci_hcd *xhci)
{
guard(spinlock_irqsave)(&xhci->lock);
for (int i = 1; i < HC_MAX_SLOTS; i++) {
if (xhci->devs[i] && xhci->devs[i]->sideband)
return true;
}
return false;
}
Thanks
Mathias
On Tue, Feb 3, 2026 at 10:14 PM Mathias Nyman
<mathias.nyman@linux.intel.com> wrote:
>
> On 2/2/26 12:03, Guan-Yu Lin wrote:
> > On Sat, Jan 31, 2026 at 8:15 PM Greg KH <gregkh@linuxfoundation.org> wrote:
> >>
> >> On Fri, Jan 30, 2026 at 07:47:46AM +0000, Guan-Yu Lin wrote:
> >>> When a USB device is disconnected or a driver is unbound, the USB core
> >>> invokes the driver's disconnect callback while holding the udev device
> >>> lock. If the driver calls xhci_sideband_unregister(), it eventually
> >>> reaches usb_offload_put(), which attempts to acquire the same udev
> >>> lock, resulting in a self-deadlock.
> >>>
> >>> Introduce lockless variants __usb_offload_get() and __usb_offload_put()
> >>> to allow modifying the offload usage count when the device lock is
> >>> already held. These helpers use device_lock_assert() to ensure callers
> >>> meet the locking requirements.
> >>
> >> Ugh. Didn't I warn about this when the original functions were added?
> >>
> >> Adding functions with __ is a mess, please make these names, if you
> >> _REALLY_ need them, obvious that this is a no lock function.
> >>
> >> And now that you added the lockless functions, are there any in-kernel
> >> users of the locked versions? At a quick glance I didn't see them, did
> >> I miss it somewhere?
> >>
> >> thanks,
> >>
> >> greg k-h
> >
> > Hi Greg,
> >
> > You are right; xhci-sideband.c is the only in-kernel user of the
> > locked versions. I will rename the __ functions to usb_offload_* and
> > remove the locked variants in the next version to clean up the API.
> >
> > Regarding the deadlock fix itself, we have analyzed two potential
> > solutions. The core issue is that xhci_sideband_unregister() (and
> > xhci_sideband_remove_interrupter()) needs to decrement the offload
> > usage count (which requires the USB device lock), but it is called
> > from the disconnect path where that lock is already held.
> >
> > Option A: Fix the Callers of xhci_sideband functions
> > In this approach, we keep the usb_offload calls inside the
> > xhci_sideband functions but replace the internal usb_lock_device()
> > with device_lock_assert(). We then update callers in
> > qc_audio_offload.c to explicitly acquire the lock.
> > This ensures the offload count remains tightly coupled with the
> > interrupter's lifecycle, though it effectively changes the API
> > contract: calling xHCI sideband functions now requires holding the USB
> > device lock.
> >
> > Option B: Decouple usb_offload functions from xhci_sideband functions
> > In this approach, we strip the usb_offload calls out of xhci_sideband
> > functions entirely. The client driver (qc_audio_offload) becomes
> > responsible for the full transaction: acquiring the lock, managing
> > usb_offload_get/put(), and creating/removing the interrupter. This
> > restores clean encapsulation (xHCI functions only handle hardware),
> > but it places the burden on the client driver to correctly balance the
> > usb_offload calls.
> >
> > I lean towards Option A to ensure the offload count implies an active
> > interrupter by design, but please let me know if you prefer the
> > cleaner separation of Option B.
>
> I would prefer option B
> Decouple the offload from sideband.
>
> The secondary interrupter in sideband was specifically createad for
> qc_audio_offload.
>
> Vendors using the xHCI hardware Audio sideband Capability (xHCI 7.9)
> won't use a secondary interrupter, but might sill want to prevent suspending
> the device. So it shuold be better to make this decision in the class driver.
>
> The offload count shoudn't be that complicated. Isn't it binary at the moment?
> We don't allow more than one sideband per device, and it can only have one
> interrupter.
>
> I unfortunately couldn't participate in the review and development of
> drivers/usb/core/offload.c, but my original idea before it was implemented
> was to keep usb core out of sideband as much as possible as its not really
> a part of usb specification.
>
> This is also why I added the sideband pointer to struct xhci_virt_device.
> It allows us to figure out if a device is dedicated for sideband use.
>
> so xhci_sideband_check() could be something like
>
> bool xhci_sideband_check(struct xhci_hcd *xhci)
> {
> guard(spinlock_irqsave)(&xhci->lock);
>
> for (int i = 1; i < HC_MAX_SLOTS; i++) {
> if (xhci->devs[i] && xhci->devs[i]->sideband)
> return true;
> }
> return false;
> }
>
> Thanks
> Mathias
Hi Mathias,
Thanks for the feedback.
I will proceed with Option B as you suggested. Decoupling the offload
logic from the sideband mechanism seems cleaner and places the
responsibility correctly on the class driver (qc_audio_offload) to
manage the offload state.
I will implement the following changes in v2:
1. API Cleanup: As Greg requested, I will rename __usb_offload_* to
usb_offload_* and remove the locked variants. These functions will use
device_lock_assert() to ensure the caller holds the lock.
2. Class Driver Logic: qc_audio_offload will handle locking udev and
calling usb_offload_get/put() directly.
Regarding xhci_sideband_check():
I have a concern regarding power management with the proposed check:
if (xhci->devs[i] && xhci->devs[i]->sideband)
return true;
vdev->sideband is assigned during xhci_sideband_register(), which
happens when the class driver probes (device connection), and it
persists until disconnect. If we use this check, the xHCI controller
will be prevented from PM suspending (system suspend) as long as the
device is connected, even if it is idle (not playing audio).
For mobile power optimization, we need to allow the controller to
suspend when the sideband is registered but idle.
Since we are proceeding with Option B, the class driver will be
maintaining the udev->offload_usage count via usb_offload_get/put(). I
propose we still rely on usb_offload_check() (or check offload_usage)
within the xHCI sideband check. This ensures we only block or adjust
the PM suspend flow only when there is active data transfer.
Regards,
Guan-Yu
On 2/4/26 11:15, Guan-Yu Lin wrote: > Regarding xhci_sideband_check(): > I have a concern regarding power management with the proposed check: > > if (xhci->devs[i] && xhci->devs[i]->sideband) > return true; > > vdev->sideband is assigned during xhci_sideband_register(), which > happens when the class driver probes (device connection), and it > persists until disconnect. If we use this check, the xHCI controller > will be prevented from PM suspending (system suspend) as long as the > device is connected, even if it is idle (not playing audio). > For mobile power optimization, we need to allow the controller to > suspend when the sideband is registered but idle. > > Since we are proceeding with Option B, the class driver will be > maintaining the udev->offload_usage count via usb_offload_get/put(). I > propose we still rely on usb_offload_check() (or check offload_usage) > within the xHCI sideband check. This ensures we only block or adjust > the PM suspend flow only when there is active data transfer. Sounds reasonable to me Thanks Mathias
© 2016 - 2026 Red Hat, Inc.