Message ID | 20221109221749.8210-1-ftoth@exalondelft.nl |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp592293wru; Wed, 9 Nov 2022 14:24:15 -0800 (PST) X-Google-Smtp-Source: AMsMyM6fwTrmIig0irT1EsWAQBYYE1CxRH9kM2tHDQLm3ChoMFLkLeP2xHNM4HlFBmGDv4z72Jbq X-Received: by 2002:a17:90a:2f03:b0:213:c57c:f062 with SMTP id s3-20020a17090a2f0300b00213c57cf062mr58575354pjd.35.1668032655232; Wed, 09 Nov 2022 14:24:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668032655; cv=none; d=google.com; s=arc-20160816; b=EKxYcEP+sCNtwvHnrBAqDmTq1HFH3okenKxXFMTGvycZbcNPx7FIwy3Yo1MuPfnyKT RE2AFj+MqJL2Pqi737QycdUxKOqyto7oS1po+JKMLEBFdsMgiwv0rkRhO2mEHTrzkr+z Z5qbmo8kgEkfEychUIJLMArEjPIgZi5fYc05jeH5L94Usf7arNo6eojPusCM3ON4v6dF BHzQiSohZ/lqhaFZbS8v49EzeowG9dqmUsyF8fOdPr8QLUnZufu4dPa+wouTafGeQlNG xQwBBJZ+ctmkd3fE6XEQJdaG31ohBi3VFFPoHjta9ot9JujGPI9nBYG5SlRlNAXcGTda CVkA== 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=BwQD9pj5b/WWSsnWxPYCsQ/PgXjWas3i27VLj8Y6Clc=; b=EgiA2MBCF+C6cSvuwbX5hH0H2cZuErUGvs1ijZZx2q2gRD4K6wMtCukJq92MwtAOfd sD1mxMycgwCBc2ILf0nB58Dgfk9mtjKtgqGXq0N+V3vGOHRV/NjTbOuF3t5UlXJZPcvi 6ScRBCwKe3VXE72s2dZLcz8XZfHqIlpEiet91aeWC9eWeKy5r6Yl8hQl5XFzWc7Ul81C VMy5XjjUafG/glaUxoA4cNQyux+tg16vB8Qnof7lbqDDX4IB1HMZ1rYbtyoPXk1xXF51 4eZlEEQh1HlQfKAL+YJjSQJTP7LOujKH/ClkHFDYIJrD3T7t5jEG+i4e1x8Y/zia9rIz fT4w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@exalondelft.nl header.s=whs1 header.b="ZkY8uv6/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=exalondelft.nl Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f4-20020a635104000000b0043ac3ec9d9esi19324194pgb.595.2022.11.09.14.24.01; Wed, 09 Nov 2022 14:24:15 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@exalondelft.nl header.s=whs1 header.b="ZkY8uv6/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=exalondelft.nl Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230262AbiKIWUE (ORCPT <rfc822;dexuan.linux@gmail.com> + 99 others); Wed, 9 Nov 2022 17:20:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229784AbiKIWUC (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 9 Nov 2022 17:20:02 -0500 X-Greylist: delayed 61 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Wed, 09 Nov 2022 14:19:59 PST Received: from mailfilter06-out40.webhostingserver.nl (mailfilter06-out40.webhostingserver.nl [195.211.73.79]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC4BAF03D for <linux-kernel@vger.kernel.org>; Wed, 9 Nov 2022 14:19:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=exalondelft.nl; s=whs1; h=content-transfer-encoding:mime-version:message-id:date:subject:cc:to:from: from; bh=BwQD9pj5b/WWSsnWxPYCsQ/PgXjWas3i27VLj8Y6Clc=; b=ZkY8uv6/hN9/FoAwFfXnWm4GMQg7cJ1jSyMvQ7tJ+ilUOB7nPzqBfUU8u/Z2Snwf1/rbGnOPQvmRA x4K23/yrAMk6SoyyKB9dEolvHKnk0AHgF6bWTNPXFG7pjTfsyiyxWMOOec/B9KdKGtY+3oUTBdEQN0 NSAp+DGOdSRPl3ctQAjzhVRqft37d73lqpX5/3cyuq1oTGW+JOPllcQb0MmM1CVOW9WZBJR2IFirVm aYBgmvkm/Low6Sf6QtTClCfZILKJWtJ+0ZmOqaPC/UQhOy0vULvq7pXS4KY/5Xn4b6sfod+Rhjgrdo HR8ICGNM9BzzHnCac3HStBcVZzQ+2rw== X-Halon-ID: 7f4b7a72-607c-11ed-837b-001a4a4cb958 Received: from s198.webhostingserver.nl (s198.webhostingserver.nl [141.138.168.154]) by mailfilter06.webhostingserver.nl (Halon) with ESMTPSA id 7f4b7a72-607c-11ed-837b-001a4a4cb958; Wed, 09 Nov 2022 23:18:54 +0100 (CET) Received: from 2a02-a466-68ed-1-6127-ee99-b8c1-12c4.fixed6.kpn.net ([2a02:a466:68ed:1:6127:ee99:b8c1:12c4] helo=localhost.localdomain) by s198.webhostingserver.nl with esmtpa (Exim 4.96) (envelope-from <ftoth@exalondelft.nl>) id 1ostPK-002HIn-0s; Wed, 09 Nov 2022 23:18:54 +0100 From: Ferry Toth <ftoth@exalondelft.nl> To: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Sean Anderson <sean.anderson@seco.com>, Liu Shixin <liushixin2@huawei.com>, Stephen Boyd <stephen.boyd@linaro.org>, Andrey Smirnov <andrew.smirnov@gmail.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Ferry Toth <ftoth@exalondelft.nl> Subject: [PATCH v1 1/1] usb: ulpi: defer ulpi_register on ulpi_read_id timeout Date: Wed, 9 Nov 2022 23:17:49 +0100 Message-Id: <20221109221749.8210-1-ftoth@exalondelft.nl> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Antivirus-Scanner: Clean mail though you should still use an Antivirus X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749059009417227040?= X-GMAIL-MSGID: =?utf-8?q?1749059009417227040?= |
Series |
[v1,1/1] usb: ulpi: defer ulpi_register on ulpi_read_id timeout
|
|
Commit Message
Ferry Toth
Nov. 9, 2022, 10:17 p.m. UTC
Since commit 0f010171
Dual Role support on Intel Merrifield platform broke due to rearranging
the call to dwc3_get_extcon().
It appears to be caused by ulpi_read_id() on the first test write failing
with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via
DT when the test write fails and returns 0 in that case even if DT does not
provide the phy. Due to the timeout being masked dwc3 probe continues by
calling dwc3_core_soft_reset() followed by dwc3_get_extcon() which happens
to return -EPROBE_DEFER. On deferred probe ulpi_read_id() finally succeeds.
This patch changes ulpi_read_id() to return -ETIMEDOUT when it occurs and
catches the error in dwc3_core_init(). It handles the error by calling
dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On deferred
probe ulpi_read_id() again succeeds.
Signed-off-by: Ferry Toth <ftoth@exalondelft.nl>
---
drivers/usb/common/ulpi.c | 5 +++--
drivers/usb/dwc3/core.c | 5 ++++-
2 files changed, 7 insertions(+), 3 deletions(-)
Comments
Hi Ferry, On Wed, Nov 09, 2022, Ferry Toth wrote: > Since commit 0f010171 > Dual Role support on Intel Merrifield platform broke due to rearranging > the call to dwc3_get_extcon(). > > It appears to be caused by ulpi_read_id() on the first test write failing > with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via > DT when the test write fails and returns 0 in that case even if DT does not > provide the phy. Due to the timeout being masked dwc3 probe continues by > calling dwc3_core_soft_reset() followed by dwc3_get_extcon() which happens > to return -EPROBE_DEFER. On deferred probe ulpi_read_id() finally succeeds. > > This patch changes ulpi_read_id() to return -ETIMEDOUT when it occurs and > catches the error in dwc3_core_init(). It handles the error by calling > dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On deferred > probe ulpi_read_id() again succeeds. > > Signed-off-by: Ferry Toth <ftoth@exalondelft.nl> > --- > drivers/usb/common/ulpi.c | 5 +++-- > drivers/usb/dwc3/core.c | 5 ++++- > 2 files changed, 7 insertions(+), 3 deletions(-) > Can you split the dwc3 change and ulpi change to separate patches? > diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c > index d7c8461976ce..d8f22bc2f9d0 100644 > --- a/drivers/usb/common/ulpi.c > +++ b/drivers/usb/common/ulpi.c > @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) > > /* Test the interface */ > ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); > - if (ret < 0) > - goto err; > + if (ret < 0) { > + return ret; > + } > > ret = ulpi_read(ulpi, ULPI_SCRATCH); > if (ret < 0) > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 648f1c570021..e293ef70039b 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) > > if (!dwc->ulpi_ready) { > ret = dwc3_core_ulpi_init(dwc); > - if (ret) > + if (ret) { > + dwc3_core_soft_reset(dwc); We shouldn't need to do soft reset here. The controller shouldn't be at a bad/incorrect state at this point to warrant a soft-reset. There will be a soft-reset when it goes through the initialization again. > + ret = -EPROBE_DEFER; We shouldn't automatically set every error status to correspond to -EPROBE_DEFER. Check only the approapriate error codes (-ETIMEDOUT + any other?). > goto err0; > + } > dwc->ulpi_ready = true; > } > > -- > 2.34.1 > Thanks, Thinh
(sorry sent html with previous attempt) On 10-11-2022 01:06, Thinh Nguyen wrote: > Hi Ferry, > > On Wed, Nov 09, 2022, Ferry Toth wrote: >> Since commit 0f010171 >> Dual Role support on Intel Merrifield platform broke due to rearranging >> the call to dwc3_get_extcon(). >> >> It appears to be caused by ulpi_read_id() on the first test write failing >> with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via >> DT when the test write fails and returns 0 in that case even if DT does not >> provide the phy. Due to the timeout being masked dwc3 probe continues by >> calling dwc3_core_soft_reset() followed by dwc3_get_extcon() which happens >> to return -EPROBE_DEFER. On deferred probe ulpi_read_id() finally succeeds. >> >> This patch changes ulpi_read_id() to return -ETIMEDOUT when it occurs and >> catches the error in dwc3_core_init(). It handles the error by calling >> dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On deferred >> probe ulpi_read_id() again succeeds. >> >> Signed-off-by: Ferry Toth<ftoth@exalondelft.nl> >> --- >> drivers/usb/common/ulpi.c | 5 +++-- >> drivers/usb/dwc3/core.c | 5 ++++- >> 2 files changed, 7 insertions(+), 3 deletions(-) >> > Can you split the dwc3 change and ulpi change to separate patches? Thanks for your comments. I will send v2 >> diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c >> index d7c8461976ce..d8f22bc2f9d0 100644 >> --- a/drivers/usb/common/ulpi.c >> +++ b/drivers/usb/common/ulpi.c >> @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) >> >> /* Test the interface */ >> ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); >> - if (ret < 0) >> - goto err; >> + if (ret < 0) { >> + return ret; >> + } >> >> ret = ulpi_read(ulpi, ULPI_SCRATCH); >> if (ret < 0) >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >> index 648f1c570021..e293ef70039b 100644 >> --- a/drivers/usb/dwc3/core.c >> +++ b/drivers/usb/dwc3/core.c >> @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) >> >> if (!dwc->ulpi_ready) { >> ret = dwc3_core_ulpi_init(dwc); >> - if (ret) >> + if (ret) { >> + dwc3_core_soft_reset(dwc); > We shouldn't need to do soft reset here. The controller shouldn't be at > a bad/incorrect state at this point to warrant a soft-reset. There will > be a soft-reset when it goes through the initialization again. It doesn't go through the initialization again unless we set -EPROBE_DEFER. And when we make ulpi_read_id() return -EPROBE_DEFER it will goto err0 here, so skips dwc3_core_soft_reset. Do you mean you prefer something like: if (ret) { if (ret == -ETIMEDOUT) ret = -EPROBE_DEFER; else goto err0; } >> + ret = -EPROBE_DEFER; > We shouldn't automatically set every error status to correspond to > -EPROBE_DEFER. Check only the approapriate error codes (-ETIMEDOUT + > any other?). Other could be -ENOMEM. I think no need to do any new handling for that. >> goto err0; >> + } >> dwc->ulpi_ready = true; >> } >> >> -- >> 2.34.1 >> > Thanks, > Thinh
On Wed, Nov 09, 2022 at 11:17:49PM +0100, Ferry Toth wrote: > Since commit 0f010171 > Dual Role support on Intel Merrifield platform broke due to rearranging > the call to dwc3_get_extcon(). > > It appears to be caused by ulpi_read_id() on the first test write failing > with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via > DT when the test write fails and returns 0 in that case even if DT does not > provide the phy. Due to the timeout being masked dwc3 probe continues by > calling dwc3_core_soft_reset() followed by dwc3_get_extcon() which happens > to return -EPROBE_DEFER. On deferred probe ulpi_read_id() finally succeeds. > > This patch changes ulpi_read_id() to return -ETIMEDOUT when it occurs and > catches the error in dwc3_core_init(). It handles the error by calling > dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On deferred > probe ulpi_read_id() again succeeds. > > Signed-off-by: Ferry Toth <ftoth@exalondelft.nl> > --- > drivers/usb/common/ulpi.c | 5 +++-- > drivers/usb/dwc3/core.c | 5 ++++- > 2 files changed, 7 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c > index d7c8461976ce..d8f22bc2f9d0 100644 > --- a/drivers/usb/common/ulpi.c > +++ b/drivers/usb/common/ulpi.c > @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) > > /* Test the interface */ > ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); > - if (ret < 0) > - goto err; > + if (ret < 0) { > + return ret; > + } No need for the curly brackets. thanks,
Hi Op 10-11-2022 om 13:45 schreef Ferry Toth: > (sorry sent html with previous attempt) > > On 10-11-2022 01:06, Thinh Nguyen wrote: >> Hi Ferry, >> >> On Wed, Nov 09, 2022, Ferry Toth wrote: >>> Since commit 0f010171 >>> Dual Role support on Intel Merrifield platform broke due to rearranging >>> the call to dwc3_get_extcon(). >>> >>> It appears to be caused by ulpi_read_id() on the first test write >>> failing >>> with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy >>> via >>> DT when the test write fails and returns 0 in that case even if DT >>> does not >>> provide the phy. Due to the timeout being masked dwc3 probe continues by >>> calling dwc3_core_soft_reset() followed by dwc3_get_extcon() which >>> happens >>> to return -EPROBE_DEFER. On deferred probe ulpi_read_id() finally >>> succeeds. >>> >>> This patch changes ulpi_read_id() to return -ETIMEDOUT when it occurs >>> and >>> catches the error in dwc3_core_init(). It handles the error by calling >>> dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On >>> deferred >>> probe ulpi_read_id() again succeeds. >>> >>> Signed-off-by: Ferry Toth<ftoth@exalondelft.nl> >>> --- >>> drivers/usb/common/ulpi.c | 5 +++-- >>> drivers/usb/dwc3/core.c | 5 ++++- >>> 2 files changed, 7 insertions(+), 3 deletions(-) >>> >> Can you split the dwc3 change and ulpi change to separate patches? > > Thanks for your comments. > > I will send v2 > >>> diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c >>> index d7c8461976ce..d8f22bc2f9d0 100644 >>> --- a/drivers/usb/common/ulpi.c >>> +++ b/drivers/usb/common/ulpi.c >>> @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) >>> /* Test the interface */ >>> ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); >>> - if (ret < 0) >>> - goto err; >>> + if (ret < 0) { >>> + return ret; >>> + } >>> ret = ulpi_read(ulpi, ULPI_SCRATCH); >>> if (ret < 0) >>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >>> index 648f1c570021..e293ef70039b 100644 >>> --- a/drivers/usb/dwc3/core.c >>> +++ b/drivers/usb/dwc3/core.c >>> @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) >>> if (!dwc->ulpi_ready) { >>> ret = dwc3_core_ulpi_init(dwc); >>> - if (ret) >>> + if (ret) { >>> + dwc3_core_soft_reset(dwc); >> We shouldn't need to do soft reset here. The controller shouldn't be at >> a bad/incorrect state at this point to warrant a soft-reset. There will >> be a soft-reset when it goes through the initialization again. > > It doesn't go through the initialization again unless we set > -EPROBE_DEFER. And when we make ulpi_read_id() return -EPROBE_DEFER it > will goto err0 here, so skips dwc3_core_soft_reset. > > Do you mean you prefer something like: > > if (ret) { > > if (ret == -ETIMEDOUT) ret = -EPROBE_DEFER; > > else goto err0; > > } I just tested, and calling dwc3_core_soft_reset() proves to be necessary as we need to goto err0 directly after. Else ret is overwritten and -EPROBE_DEFER lost. >>> + ret = -EPROBE_DEFER; >> We shouldn't automatically set every error status to correspond to >> -EPROBE_DEFER. Check only the approapriate error codes (-ETIMEDOUT + >> any other?). > Other could be -ENOMEM. I think no need to do any new handling for that. >>> goto err0; >>> + } >>> dwc->ulpi_ready = true; >>> } >>> -- >>> 2.34.1 >>> >> Thanks, >> Thinh
On Thu, Nov 10, 2022, Ferry Toth wrote: > Hi > > Op 10-11-2022 om 13:45 schreef Ferry Toth: > > (sorry sent html with previous attempt) > > > > On 10-11-2022 01:06, Thinh Nguyen wrote: > > > Hi Ferry, > > > > > > On Wed, Nov 09, 2022, Ferry Toth wrote: > > > > Since commit 0f010171 > > > > Dual Role support on Intel Merrifield platform broke due to rearranging > > > > the call to dwc3_get_extcon(). > > > > > > > > It appears to be caused by ulpi_read_id() on the first test > > > > write failing > > > > with -ETIMEDOUT. Currently ulpi_read_id() expects to discover > > > > the phy via > > > > DT when the test write fails and returns 0 in that case even if > > > > DT does not > > > > provide the phy. Due to the timeout being masked dwc3 probe continues by > > > > calling dwc3_core_soft_reset() followed by dwc3_get_extcon() > > > > which happens > > > > to return -EPROBE_DEFER. On deferred probe ulpi_read_id() > > > > finally succeeds. > > > > > > > > This patch changes ulpi_read_id() to return -ETIMEDOUT when it > > > > occurs and > > > > catches the error in dwc3_core_init(). It handles the error by calling > > > > dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On > > > > deferred > > > > probe ulpi_read_id() again succeeds. > > > > > > > > Signed-off-by: Ferry Toth<ftoth@exalondelft.nl> > > > > --- > > > > drivers/usb/common/ulpi.c | 5 +++-- > > > > drivers/usb/dwc3/core.c | 5 ++++- > > > > 2 files changed, 7 insertions(+), 3 deletions(-) > > > > > > > Can you split the dwc3 change and ulpi change to separate patches? > > > > Thanks for your comments. > > > > I will send v2 > > > > > > diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c > > > > index d7c8461976ce..d8f22bc2f9d0 100644 > > > > --- a/drivers/usb/common/ulpi.c > > > > +++ b/drivers/usb/common/ulpi.c > > > > @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) > > > > /* Test the interface */ > > > > ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); > > > > - if (ret < 0) > > > > - goto err; > > > > + if (ret < 0) { > > > > + return ret; > > > > + } > > > > ret = ulpi_read(ulpi, ULPI_SCRATCH); > > > > if (ret < 0) > > > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > > > > index 648f1c570021..e293ef70039b 100644 > > > > --- a/drivers/usb/dwc3/core.c > > > > +++ b/drivers/usb/dwc3/core.c > > > > @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) > > > > if (!dwc->ulpi_ready) { > > > > ret = dwc3_core_ulpi_init(dwc); > > > > - if (ret) > > > > + if (ret) { > > > > + dwc3_core_soft_reset(dwc); > > > We shouldn't need to do soft reset here. The controller shouldn't be at > > > a bad/incorrect state at this point to warrant a soft-reset. There will > > > be a soft-reset when it goes through the initialization again. > > > > It doesn't go through the initialization again unless we set > > -EPROBE_DEFER. And when we make ulpi_read_id() return -EPROBE_DEFER it > > will goto err0 here, so skips dwc3_core_soft_reset. > > > > Do you mean you prefer something like: > > > > if (ret) { > > > > if (ret == -ETIMEDOUT) ret = -EPROBE_DEFER; > > > > else goto err0; Why "else"? But I saw you remove that in the new patch. > > > > } > > I just tested, and calling dwc3_core_soft_reset() proves to be necessary as > we need to goto err0 directly after. Else ret is overwritten and > -EPROBE_DEFER lost. Looks like there's a strange dependency problem here. * The setup needs a soft-reset before ulpi registration * The ulpi registration needs to go before the phy initialization * The soft-reset should be called after the phy initialization I can't explain the actual issue here, and we can't debug further because to look into it further would require looking at internal signals. This soft-reset and -EPROBE_DEFER seems to be a workaround to this dependency problem. Instead of using -EPROBE_DEFER, can you do this: diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2f0a9679686f..5a1aaf3741ec 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1097,6 +1097,8 @@ static int dwc3_core_init(struct dwc3 *dwc) goto err0; if (!dwc->ulpi_ready) { + /* Add comment */ + dwc3_core_soft_reset(dwc); ret = dwc3_core_ulpi_init(dwc); if (ret) goto err0; > > > > > + ret = -EPROBE_DEFER; > > > We shouldn't automatically set every error status to correspond to > > > -EPROBE_DEFER. Check only the approapriate error codes (-ETIMEDOUT + > > > any other?). > > Other could be -ENOMEM. I think no need to do any new handling for that. There's also -EINVAL and some others too. Regardless, if it's -ENOMEM, then it should not return -EPROBE_DEFER. > > > > goto err0; > > > > + } > > > > dwc->ulpi_ready = true; > > > > } > > > > Thanks, Thinh
Hi, Op 11-11-2022 om 02:31 schreef Thinh Nguyen: > On Thu, Nov 10, 2022, Ferry Toth wrote: >> Hi >> >> Op 10-11-2022 om 13:45 schreef Ferry Toth: >>> (sorry sent html with previous attempt) >>> >>> On 10-11-2022 01:06, Thinh Nguyen wrote: >>>> Hi Ferry, >>>> >>>> On Wed, Nov 09, 2022, Ferry Toth wrote: >>>>> Since commit 0f010171 >>>>> Dual Role support on Intel Merrifield platform broke due to rearranging >>>>> the call to dwc3_get_extcon(). >>>>> >>>>> It appears to be caused by ulpi_read_id() on the first test >>>>> write failing >>>>> with -ETIMEDOUT. Currently ulpi_read_id() expects to discover >>>>> the phy via >>>>> DT when the test write fails and returns 0 in that case even if >>>>> DT does not >>>>> provide the phy. Due to the timeout being masked dwc3 probe continues by >>>>> calling dwc3_core_soft_reset() followed by dwc3_get_extcon() >>>>> which happens >>>>> to return -EPROBE_DEFER. On deferred probe ulpi_read_id() >>>>> finally succeeds. >>>>> >>>>> This patch changes ulpi_read_id() to return -ETIMEDOUT when it >>>>> occurs and >>>>> catches the error in dwc3_core_init(). It handles the error by calling >>>>> dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On >>>>> deferred >>>>> probe ulpi_read_id() again succeeds. >>>>> >>>>> Signed-off-by: Ferry Toth<ftoth@exalondelft.nl> >>>>> --- >>>>> drivers/usb/common/ulpi.c | 5 +++-- >>>>> drivers/usb/dwc3/core.c | 5 ++++- >>>>> 2 files changed, 7 insertions(+), 3 deletions(-) >>>>> >>>> Can you split the dwc3 change and ulpi change to separate patches? >>> >>> Thanks for your comments. >>> >>> I will send v2 >>> >>>>> diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c >>>>> index d7c8461976ce..d8f22bc2f9d0 100644 >>>>> --- a/drivers/usb/common/ulpi.c >>>>> +++ b/drivers/usb/common/ulpi.c >>>>> @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) >>>>> /* Test the interface */ >>>>> ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); >>>>> - if (ret < 0) >>>>> - goto err; >>>>> + if (ret < 0) { >>>>> + return ret; >>>>> + } >>>>> ret = ulpi_read(ulpi, ULPI_SCRATCH); >>>>> if (ret < 0) >>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >>>>> index 648f1c570021..e293ef70039b 100644 >>>>> --- a/drivers/usb/dwc3/core.c >>>>> +++ b/drivers/usb/dwc3/core.c >>>>> @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) >>>>> if (!dwc->ulpi_ready) { >>>>> ret = dwc3_core_ulpi_init(dwc); >>>>> - if (ret) >>>>> + if (ret) { >>>>> + dwc3_core_soft_reset(dwc); >>>> We shouldn't need to do soft reset here. The controller shouldn't be at >>>> a bad/incorrect state at this point to warrant a soft-reset. There will >>>> be a soft-reset when it goes through the initialization again. >>> >>> It doesn't go through the initialization again unless we set >>> -EPROBE_DEFER. And when we make ulpi_read_id() return -EPROBE_DEFER it >>> will goto err0 here, so skips dwc3_core_soft_reset. >>> >>> Do you mean you prefer something like: >>> >>> if (ret) { >>> >>> if (ret == -ETIMEDOUT) ret = -EPROBE_DEFER; >>> >>> else goto err0; > > Why "else"? But I saw you remove that in the new patch. > >>> >>> } >> >> I just tested, and calling dwc3_core_soft_reset() proves to be necessary as >> we need to goto err0 directly after. Else ret is overwritten and >> -EPROBE_DEFER lost. > > Looks like there's a strange dependency problem here. > * The setup needs a soft-reset before ulpi registration > * The ulpi registration needs to go before the phy initialization > * The soft-reset should be called after the phy initialization > > I can't explain the actual issue here, and we can't debug further > because to look into it further would require looking at internal > signals. > > This soft-reset and -EPROBE_DEFER seems to be a workaround to this > dependency problem. Instead of using -EPROBE_DEFER, can you do this: > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 2f0a9679686f..5a1aaf3741ec 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -1097,6 +1097,8 @@ static int dwc3_core_init(struct dwc3 *dwc) > goto err0; > > if (!dwc->ulpi_ready) { > + /* Add comment */ > + dwc3_core_soft_reset(dwc); > ret = dwc3_core_ulpi_init(dwc); > if (ret) > goto err0; > This indeed fixes the issue as well. Here is the trace: # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 0) | /* start_event: (dwc3_probe+0x0/0x1910) */ 0) 7.070 us | dwc3_clk_enable.part.0(); 0) 5.480 us | extcon_get_extcon_dev(); 0) + 10.230 us | dwc3_runtime_idle(); 0) | /* end_event: (platform_probe+0x3f/0xa0 <- dwc3_probe) */ ** multiple defers while waiting for extcon 0) | /* start_event: (dwc3_probe+0x0/0x1910) */ 0) 7.320 us | dwc3_clk_enable.part.0(); 0) 6.830 us | extcon_get_extcon_dev(); 0) | dwc3_core_init() { 0) + 29.200 us | dwc3_core_soft_reset.part.0(); 0) | dwc3_ulpi_init() { 0) | ulpi_register_interface() { 0) | dwc3_ulpi_write() { 0) 3.380 us | dwc3_ulpi_busyloop(); ** without this patch this one times out after 10000us 0) 7.710 us | } 0) | dwc3_ulpi_read() { 0) 3.060 us | dwc3_ulpi_busyloop(); 0) 7.210 us | } 0) | dwc3_ulpi_read() { 0) 2.830 us | dwc3_ulpi_busyloop(); 0) 6.690 us | } 0) | dwc3_ulpi_read() { 0) 2.880 us | dwc3_ulpi_busyloop(); 0) 6.670 us | } 0) | dwc3_ulpi_read() { 0) 2.940 us | dwc3_ulpi_busyloop(); 0) 6.690 us | } 0) | dwc3_ulpi_read() { 0) 2.870 us | dwc3_ulpi_busyloop(); 0) 6.620 us | } 0) + 18.150 us | ulpi_uevent(); 0) 5.990 us | ulpi_match(); 0) | ulpi_probe() { 0) | tusb1210_probe() { 0) | ulpi_read() { 0) | dwc3_ulpi_read() { 0) 4.440 us | dwc3_ulpi_busyloop(); 0) 9.600 us | } 0) + 15.770 us | } 0) | ulpi_write() { 0) | dwc3_ulpi_write() { 0) 3.270 us | dwc3_ulpi_busyloop(); 0) 6.820 us | } 0) + 11.020 us | } 0) ! 407.540 us | } 0) ! 416.980 us | } 0) 9.800 us | ulpi_uevent(); 0) * 18604.00 us | } 0) * 18611.20 us | } 0) + 30.570 us | dwc3_core_soft_reset.part.0(); 0) | tusb1210_power_on() { 1) | extcon_set_state_sync() { 1) 5.330 us | extcon_set_state.part.0(); 1) + 90.550 us | extcon_sync.part.0(); 1) ! 113.670 us | } 1) + 19.450 us | ulpi_uevent(); 0) + 13.640 us | ulpi_uevent(); 1) + 13.980 us | ulpi_uevent(); 0) + 15.960 us | ulpi_uevent(); 0) | ulpi_write() { 0) | dwc3_ulpi_write() { 0) * 10239.47 us | dwc3_ulpi_busyloop(); 0) * 10250.57 us | } 0) * 10265.09 us | } 0) * 69518.95 us | } 0) 5.740 us | dwc3_event_buffers_setup(); 0) * 88241.02 us | } /* dwc3_core_init */ 0) ! 104.900 us | dwc3_debugfs_init(); 0) | dwc3_drd_init() { 0) 4.720 us | extcon_register_notifier(); 0) | extcon_get_state() { 0) 2.640 us | extcon_get_state.part.0(); 0) 6.460 us | } 0) + 14.460 us | dwc3_set_mode(); 0) + 43.300 us | } 0) | /* end_event: (platform_probe+0x3f/0xa0 <- dwc3_probe) */ Maybe this is the preferred way to go if the dwc3_core_soft_reset() doesn't hurt other users? >> >>>>> + ret = -EPROBE_DEFER; >>>> We shouldn't automatically set every error status to correspond to >>>> -EPROBE_DEFER. Check only the approapriate error codes (-ETIMEDOUT + >>>> any other?). >>> Other could be -ENOMEM. I think no need to do any new handling for that. > > There's also -EINVAL and some others too. Regardless, if it's -ENOMEM, > then it should not return -EPROBE_DEFER. > >>>>> goto err0; >>>>> + } >>>>> dwc->ulpi_ready = true; >>>>> } >>>>> > > Thanks, > Thinh
On Fri, Nov 18, 2022, Ferry Toth wrote: > Hi, > > Op 11-11-2022 om 02:31 schreef Thinh Nguyen: > > On Thu, Nov 10, 2022, Ferry Toth wrote: > > > Hi > > > > > > Op 10-11-2022 om 13:45 schreef Ferry Toth: > > > > (sorry sent html with previous attempt) > > > > > > > > On 10-11-2022 01:06, Thinh Nguyen wrote: > > > > > Hi Ferry, > > > > > > > > > > On Wed, Nov 09, 2022, Ferry Toth wrote: > > > > > > Since commit 0f010171 > > > > > > Dual Role support on Intel Merrifield platform broke due to rearranging > > > > > > the call to dwc3_get_extcon(). > > > > > > > > > > > > It appears to be caused by ulpi_read_id() on the first test > > > > > > write failing > > > > > > with -ETIMEDOUT. Currently ulpi_read_id() expects to discover > > > > > > the phy via > > > > > > DT when the test write fails and returns 0 in that case even if > > > > > > DT does not > > > > > > provide the phy. Due to the timeout being masked dwc3 probe continues by > > > > > > calling dwc3_core_soft_reset() followed by dwc3_get_extcon() > > > > > > which happens > > > > > > to return -EPROBE_DEFER. On deferred probe ulpi_read_id() > > > > > > finally succeeds. > > > > > > > > > > > > This patch changes ulpi_read_id() to return -ETIMEDOUT when it > > > > > > occurs and > > > > > > catches the error in dwc3_core_init(). It handles the error by calling > > > > > > dwc3_core_soft_reset() after which it requests -EPROBE_DEFER. On > > > > > > deferred > > > > > > probe ulpi_read_id() again succeeds. > > > > > > > > > > > > Signed-off-by: Ferry Toth<ftoth@exalondelft.nl> > > > > > > --- > > > > > > drivers/usb/common/ulpi.c | 5 +++-- > > > > > > drivers/usb/dwc3/core.c | 5 ++++- > > > > > > 2 files changed, 7 insertions(+), 3 deletions(-) > > > > > > > > > > > Can you split the dwc3 change and ulpi change to separate patches? > > > > > > > > Thanks for your comments. > > > > > > > > I will send v2 > > > > > > > > > > diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c > > > > > > index d7c8461976ce..d8f22bc2f9d0 100644 > > > > > > --- a/drivers/usb/common/ulpi.c > > > > > > +++ b/drivers/usb/common/ulpi.c > > > > > > @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) > > > > > > /* Test the interface */ > > > > > > ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); > > > > > > - if (ret < 0) > > > > > > - goto err; > > > > > > + if (ret < 0) { > > > > > > + return ret; > > > > > > + } > > > > > > ret = ulpi_read(ulpi, ULPI_SCRATCH); > > > > > > if (ret < 0) > > > > > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > > > > > > index 648f1c570021..e293ef70039b 100644 > > > > > > --- a/drivers/usb/dwc3/core.c > > > > > > +++ b/drivers/usb/dwc3/core.c > > > > > > @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) > > > > > > if (!dwc->ulpi_ready) { > > > > > > ret = dwc3_core_ulpi_init(dwc); > > > > > > - if (ret) > > > > > > + if (ret) { > > > > > > + dwc3_core_soft_reset(dwc); > > > > > We shouldn't need to do soft reset here. The controller shouldn't be at > > > > > a bad/incorrect state at this point to warrant a soft-reset. There will > > > > > be a soft-reset when it goes through the initialization again. > > > > > > > > It doesn't go through the initialization again unless we set > > > > -EPROBE_DEFER. And when we make ulpi_read_id() return -EPROBE_DEFER it > > > > will goto err0 here, so skips dwc3_core_soft_reset. > > > > > > > > Do you mean you prefer something like: > > > > > > > > if (ret) { > > > > > > > > if (ret == -ETIMEDOUT) ret = -EPROBE_DEFER; > > > > > > > > else goto err0; > > > > Why "else"? But I saw you remove that in the new patch. > > > > > > > > > > } > > > > > > I just tested, and calling dwc3_core_soft_reset() proves to be necessary as > > > we need to goto err0 directly after. Else ret is overwritten and > > > -EPROBE_DEFER lost. > > > > Looks like there's a strange dependency problem here. > > * The setup needs a soft-reset before ulpi registration > > * The ulpi registration needs to go before the phy initialization > > * The soft-reset should be called after the phy initialization > > > > I can't explain the actual issue here, and we can't debug further > > because to look into it further would require looking at internal > > signals. > > > > This soft-reset and -EPROBE_DEFER seems to be a workaround to this > > dependency problem. Instead of using -EPROBE_DEFER, can you do this: > > > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > > index 2f0a9679686f..5a1aaf3741ec 100644 > > --- a/drivers/usb/dwc3/core.c > > +++ b/drivers/usb/dwc3/core.c > > @@ -1097,6 +1097,8 @@ static int dwc3_core_init(struct dwc3 *dwc) > > goto err0; > > if (!dwc->ulpi_ready) { > > + /* Add comment */ > > + dwc3_core_soft_reset(dwc); > > ret = dwc3_core_ulpi_init(dwc); > > if (ret) > > goto err0; > > > > This indeed fixes the issue as well. Here is the trace: Thanks for the test! > > # tracer: function_graph > # > # CPU DURATION FUNCTION CALLS > # | | | | | | | > 0) | /* start_event: (dwc3_probe+0x0/0x1910) */ > 0) 7.070 us | dwc3_clk_enable.part.0(); > 0) 5.480 us | extcon_get_extcon_dev(); > 0) + 10.230 us | dwc3_runtime_idle(); > 0) | /* end_event: (platform_probe+0x3f/0xa0 <- dwc3_probe) > */ > > ** multiple defers while waiting for extcon > > 0) | /* start_event: (dwc3_probe+0x0/0x1910) */ > 0) 7.320 us | dwc3_clk_enable.part.0(); > 0) 6.830 us | extcon_get_extcon_dev(); > 0) | dwc3_core_init() { > 0) + 29.200 us | dwc3_core_soft_reset.part.0(); > 0) | dwc3_ulpi_init() { > 0) | ulpi_register_interface() { > 0) | dwc3_ulpi_write() { > 0) 3.380 us | dwc3_ulpi_busyloop(); > > ** without this patch this one times out after 10000us > > 0) 7.710 us | } > 0) | dwc3_ulpi_read() { > 0) 3.060 us | dwc3_ulpi_busyloop(); > 0) 7.210 us | } > 0) | dwc3_ulpi_read() { > 0) 2.830 us | dwc3_ulpi_busyloop(); > 0) 6.690 us | } > 0) | dwc3_ulpi_read() { > 0) 2.880 us | dwc3_ulpi_busyloop(); > 0) 6.670 us | } > 0) | dwc3_ulpi_read() { > 0) 2.940 us | dwc3_ulpi_busyloop(); > 0) 6.690 us | } > 0) | dwc3_ulpi_read() { > 0) 2.870 us | dwc3_ulpi_busyloop(); > 0) 6.620 us | } > 0) + 18.150 us | ulpi_uevent(); > 0) 5.990 us | ulpi_match(); > 0) | ulpi_probe() { > 0) | tusb1210_probe() { > 0) | ulpi_read() { > 0) | dwc3_ulpi_read() { > 0) 4.440 us | dwc3_ulpi_busyloop(); > 0) 9.600 us | } > 0) + 15.770 us | } > 0) | ulpi_write() { > 0) | dwc3_ulpi_write() { > 0) 3.270 us | dwc3_ulpi_busyloop(); > 0) 6.820 us | } > 0) + 11.020 us | } > 0) ! 407.540 us | } > 0) ! 416.980 us | } > 0) 9.800 us | ulpi_uevent(); > 0) * 18604.00 us | } > 0) * 18611.20 us | } > 0) + 30.570 us | dwc3_core_soft_reset.part.0(); > 0) | tusb1210_power_on() { > 1) | extcon_set_state_sync() { > 1) 5.330 us | extcon_set_state.part.0(); > 1) + 90.550 us | extcon_sync.part.0(); > 1) ! 113.670 us | } > 1) + 19.450 us | ulpi_uevent(); > 0) + 13.640 us | ulpi_uevent(); > 1) + 13.980 us | ulpi_uevent(); > 0) + 15.960 us | ulpi_uevent(); > 0) | ulpi_write() { > 0) | dwc3_ulpi_write() { > 0) * 10239.47 us | dwc3_ulpi_busyloop(); > 0) * 10250.57 us | } > 0) * 10265.09 us | } > 0) * 69518.95 us | } > 0) 5.740 us | dwc3_event_buffers_setup(); > 0) * 88241.02 us | } /* dwc3_core_init */ > 0) ! 104.900 us | dwc3_debugfs_init(); > 0) | dwc3_drd_init() { > 0) 4.720 us | extcon_register_notifier(); > 0) | extcon_get_state() { > 0) 2.640 us | extcon_get_state.part.0(); > 0) 6.460 us | } > 0) + 14.460 us | dwc3_set_mode(); > 0) + 43.300 us | } > 0) | /* end_event: (platform_probe+0x3f/0xa0 <- dwc3_probe) > */ > > Maybe this is the preferred way to go if the dwc3_core_soft_reset() doesn't > hurt other users? > The check you added seems to fit better for this behavior, which I'd consider a quirk. We can revisit this change if the ulpi update doesn't go through. Thanks, Thinh
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d7c8461976ce..d8f22bc2f9d0 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -206,8 +206,9 @@ static int ulpi_read_id(struct ulpi *ulpi) /* Test the interface */ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); - if (ret < 0) - goto err; + if (ret < 0) { + return ret; + } ret = ulpi_read(ulpi, ULPI_SCRATCH); if (ret < 0) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 648f1c570021..e293ef70039b 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1106,8 +1106,11 @@ static int dwc3_core_init(struct dwc3 *dwc) if (!dwc->ulpi_ready) { ret = dwc3_core_ulpi_init(dwc); - if (ret) + if (ret) { + dwc3_core_soft_reset(dwc); + ret = -EPROBE_DEFER; goto err0; + } dwc->ulpi_ready = true; }