From nobody Sat Feb 7 17:19:56 2026 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 749A5194A76 for ; Wed, 24 Dec 2025 08:21:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766564502; cv=none; b=of0/TuHLx+FkoySPccDTxMgCFOOV+0SkIYEOh5ALg//rq27YbvFSpNNV336DhYhoilYGLXHP7teJFP+HRvRcqPjL21TqttakAiyYlyC+tfUbjQHapm0I+Mivfq2ltaL9Zg0TGURQHXARW3YcluDtnYhb0ZFC0MLSWPzjpm8pc5g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766564502; c=relaxed/simple; bh=k7yvHo2ZwJ/OULW+qXOcpCYk0LIcpEE+w6+GFRBWzH4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mqGzuM+MykuOXQJi00kgLOak2qOpJDAzXMwiJjgpCAtm/TsX5jMcy7J5r4L1mmTqX+49BSeZRAFmbxjBFPnEWAUc2sJleACEQHoqsEHKpUdEPJ67iQabbBtAbAC4XYNyuv6Bb6TIJD5hiSXtHWJeLqRrMS8fCM4gBlJ2fFUzzEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kVHcS3/H; arc=none smtp.client-ip=209.85.214.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kVHcS3/H" Received: by mail-pl1-f196.google.com with SMTP id d9443c01a7336-2a07f8dd9cdso62071185ad.1 for ; Wed, 24 Dec 2025 00:21:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766564501; x=1767169301; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Fs+q/raxaG2h1x/D1IYwhRGtsaRix0PUab49pgsXyU0=; b=kVHcS3/HTKB45LtqESqYn+DPDKU4SgIab8G5gQ/YMcSuvD9aV/OJgS8x+UEMfztNTX SiHIiHEb9lYxTUbV8jxybCOm4yCt56bf2NpaQgWPQl5IK+7ZEVddiW7mcyw9Cr4fYn+n dEHBVrZXcqJClgZi3v+lE7Vj+ilRTZ3jht76Xg4GfcjzUTjP7v9QMBdNTmCXB5ftuRWt VJY8stsvqPFjQJ56SCh1RRmDXJbYVwO0Z1Eg/A9jyU90mouArQwbKW0bTGc5h6Rqy7WD rOlGnihBCdOzylme4GiRVlxfnFbiE3nLP/FgEyx9LLfgrKwDroAiVp/SKaHWe3sRbzBY macg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766564501; x=1767169301; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Fs+q/raxaG2h1x/D1IYwhRGtsaRix0PUab49pgsXyU0=; b=hhQ+VMrZcSzbH2n8o+Id8P9kwxgSiw75JUmFh+lBPasTTpM/0di4I+TDaFJeye7+s6 eJg2LYKk3Tso1uEc5FHkZrqpeIEp43YmG+mX06YBCyLNjg9ix0a1g8TByDa02YyqrkWB 17dWqTvtnwaaKLGmEwdZd343YkSRC0C3LcrujVkdE7k3grx/nD0s8pcR3kqTvJZUvfc5 m5ZaUXyfkbLxrWMljJZg8hoE8ewVxK47A7kad19cgXt+ZFBEN0hw9ueytenshXdWV7e3 sQOIu1EfQU6z+o+wj/J/X49m0bHnE9Da7h1jqrof853fzU9NhG6xnYHqDAdOnTP5DFwI KrcA== X-Forwarded-Encrypted: i=1; AJvYcCUwfFVVmhZjUDMUG0ciZSnRMp2L8KMfq5mw9x9+/VnlbQiqUC3Ps9MyDceZK78N4Jcjg1FqoYk2wXUGwPI=@vger.kernel.org X-Gm-Message-State: AOJu0YwGUOSEvLTOzTLMrhe138SGXLI00nA1zt02O6DWhlEe5xht6DTQ aPAgU/JqSkJfbTAXZDTv9nU0lqksjekwSyRzSHYYYG0iw2ia56qkote4 X-Gm-Gg: AY/fxX7KJU3XP5irAQwgkVQ09apB/9tVKl4bN1xlayySrw1PNgnGkETiJVJnL2Ij1do xpB+Sxz90btGDGzDGAsDZ+jTj08PAxOQYRT7oCgnMt3U/+DZIIDnCJgK/TliN9Gch26aVvrtn0i Mvx6ym4TzWJ8qS75YlREmHxXzsUV0B8bVhP1zlxqgeeMrBhWZ5RVXBT4Lx2HUdVBbucEsFUgKdg mi1/5Wu+xKRUk6fqoFVBkZ4E50x3oVPeIK5EqYl1lsSckJ8FpHmQDEujQg6tOE7CZhxiE7I7KEa v4EZTmvIfgJIn1cvUniXlDsLMajF6oX8rXWp0T57w6u8DYKB/SMArG4zLz4t0t4dqtd3ov4i4SQ 5sjs4GPL/Eak6pnvQCBMrET2jScXX5li+wztnZKrq9994tt+9oief2yPpjg1xR2XDxNC49gZbWp i6HCwaQRSP4lOpYmBEfP7EowZuMQ== X-Google-Smtp-Source: AGHT+IHh1af0uc/lW9BEVz9XbF25P+o5iYz7XAwVVngT5Y8+Ypc19c0CHRgEaVOPBdahuy0Aq+n/+g== X-Received: by 2002:a17:902:ec8d:b0:2a0:daa7:8a57 with SMTP id d9443c01a7336-2a2f2836573mr168213945ad.30.1766564500804; Wed, 24 Dec 2025 00:21:40 -0800 (PST) Received: from localhost.localdomain ([113.98.62.227]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a2f3c6661esm146155665ad.2.2025.12.24.00.21.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Dec 2025 00:21:40 -0800 (PST) From: Jason Sun To: gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, sunqian@senarytech.com, jason.sun689@gmail.com Subject: [PATCH v2] dwc2: Delay resume until device connection is stable Date: Wed, 24 Dec 2025 16:20:13 +0800 Message-Id: <20251224082013.87100-1-jason.sun689@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20251215125317.85624-1-sunqian@senarytech.com> References: <20251215125317.85624-1-sunqian@senarytech.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When DWC2 is used as a host with a dynamically controlled VBUS supply, VBUS may be turned off during system suspend and enabled again during resume. Some USB devices (e.g. USB mass storage) require additional time after VBUS is restored to power up and for the D+/D- line state to settle. The resume sequence may proceed too early, observe HPRT0.CONNSTS as 0, and treat an already-connected device as disconnected. This can lead to a spurious USB disconnect followed by re-enumeration, making an already-mounted filesystem unusable after resume. Even if the device reconnects later, the resume does not behave like a true restoration of the pre-suspend device state. Poll HPRT0.CONNSTS for a short, bounded period after enabling the external VBUS supply, allowing the controller to report a stable connection state and prevent spurious disconnects during resume. Without this change, resume often results in a disconnect and a new device enumeration: dwc2_enable_host_interrupts() ClearPortFeature USB_PORT_FEAT_C_SUSPEND ClearPortFeature USB_PORT_FEAT_ENABLE usb 1-1: USB disconnect, device number 3 ... usb 1-1: new high-speed USB device number 4 using dwc2 With this change applied, the controller reliably detects the device after resume and restores the link without triggering a full disconnect and re-enumeration cycle: dwc2_enable_host_interrupts() gintsts=3D05000021 gintmsk=3Df3000806 Device connected after 9 retries ClearPortFeature USB_PORT_FEAT_C_CONNECTION ClearPortFeature USB_PORT_FEAT_C_SUSPEND ... usb 1-1: reset high-speed USB device number 4 using dwc2 As a side effect, when an OTG host adapter is connected but no USB device is present, HPRT0.CONNSTS remains deasserted and the polling reaches the timeout. In this case, system resume latency may increase by the duration of the bounded wait, which is considered an acceptable tradeoff to avoid spurious disconnects and filesystem corruption. Tested on: - Kernel: v5.15.140 - Suspend mode: suspend-to-RAM (STR) - dr_mode: OTG (dual-role), host mode via OTG adapter - Devices: * USB mass storage (Aigo, Kingston, SanDisk) * USB HID (mouse, keyboard) Signed-off-by: Jason Sun --- drivers/usb/dwc2/hcd.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 60ef8092259a..96345eeb9e2f 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4404,11 +4404,15 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) return ret; } =20 +#define CONNSTS_POLL_RETRIES 80 +#define CONNSTS_POLL_DELAY_US_MIN 3000 +#define CONNSTS_POLL_DELAY_US_MAX 5000 static int _dwc2_hcd_resume(struct usb_hcd *hcd) { struct dwc2_hsotg *hsotg =3D dwc2_hcd_to_hsotg(hcd); unsigned long flags; u32 hprt0; + int retry; int ret =3D 0; =20 spin_lock_irqsave(&hsotg->lock, flags); @@ -4501,8 +4505,26 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd) spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_vbus_supply_init(hsotg); =20 - /* Wait for controller to correctly update D+/D- level */ - usleep_range(3000, 5000); + /* + * Wait for device connection to stabilize after VBUS is restored. + * Some externally powered devices may need time for D+/D- lines to settl= e. + * This runs in the resume path where sleeping is allowed. + */ + for (retry =3D 0; retry < CONNSTS_POLL_RETRIES; retry++) { + spin_lock_irqsave(&hsotg->lock, flags); + hprt0 =3D dwc2_read_hprt0(hsotg); + spin_unlock_irqrestore(&hsotg->lock, flags); + + if (hprt0 & HPRT0_CONNSTS) { + dev_dbg(hsotg->dev, + "Device connected after %d retries\n", retry); + break; + } + + usleep_range(CONNSTS_POLL_DELAY_US_MIN, + CONNSTS_POLL_DELAY_US_MAX); + } + spin_lock_irqsave(&hsotg->lock, flags); =20 /* --=20 2.25.1