From patchwork Mon Jun 7 13:14:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303563 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 936BDC47082 for ; Mon, 7 Jun 2021 13:14:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7BC78610FC for ; Mon, 7 Jun 2021 13:14:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230256AbhFGNQN (ORCPT ); Mon, 7 Jun 2021 09:16:13 -0400 Received: from mga06.intel.com ([134.134.136.31]:17596 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230251AbhFGNQN (ORCPT ); Mon, 7 Jun 2021 09:16:13 -0400 IronPort-SDR: a3K+hAc73OG/NL63kfVXQB6Zz3sHE83JNv7U+coQlrBKWCTWh5RyEmCTMbLVHmw78B6tpRPG7x GIMg7Nh6gtLA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265773969" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265773969" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:22 -0700 IronPort-SDR: o9mg1kFB2+hwleThD7WQw8LP9AsfAFCj7Ac5ibTq0UtEZQdBuQaGM+wNdb7XLq+nhOS2dKIAvj 9dUF+K2Xw5Zw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881864" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:20 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/7] usb: typec: ucsi: Always cancel the command if PPM reports BUSY condition Date: Mon, 7 Jun 2021 16:14:36 +0300 Message-Id: <20210607131442.20121-2-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This makes it possible to execute next command immediately after the busy condition. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 4e1973fbdf0dc..366c8a468bc18 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -128,8 +128,10 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd) if (ret) return ret; - if (cci & UCSI_CCI_BUSY) + if (cci & UCSI_CCI_BUSY) { + ucsi->ops->async_write(ucsi, UCSI_CANCEL, NULL, 0); return -EBUSY; + } if (!(cci & UCSI_CCI_COMMAND_COMPLETE)) return -EIO; From patchwork Mon Jun 7 13:14:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2069EC47082 for ; Mon, 7 Jun 2021 13:14:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F3B0D610FC for ; Mon, 7 Jun 2021 13:14:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230294AbhFGNQP (ORCPT ); Mon, 7 Jun 2021 09:16:15 -0400 Received: from mga06.intel.com ([134.134.136.31]:17596 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230286AbhFGNQP (ORCPT ); Mon, 7 Jun 2021 09:16:15 -0400 IronPort-SDR: tBavJunpLrIJaTDUFzwAqPVD9WU12Nlr3q/LBHCYUyA1e88O+w+a0R3QywmAO4XB6NW3PRHdFE eAUKRS/85Z4Q== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265773975" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265773975" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:23 -0700 IronPort-SDR: Rukd6daE8+rrbDufK/dGwRtteilroJL0Sg0stGAun2qE5Ec665Q2/CGRi9qJMviz+NqAK1kSo5 3qD2rzxnjxFg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881872" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:22 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/7] usb: typec: ucsi: Don't stop alt mode registration on busy condition Date: Mon, 7 Jun 2021 16:14:37 +0300 Message-Id: <20210607131442.20121-3-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org If the PPM tells it's busy, we can now simply try again. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 366c8a468bc18..a8e0e31dcddf5 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -437,8 +437,11 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient) command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); command |= UCSI_GET_ALTMODE_OFFSET(i); len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt)); - if (len <= 0) + if (len <= 0) { + if (len == -EBUSY) + continue; return len; + } /* * This code is requesting one alt mode at a time, but some PPMs From patchwork Mon Jun 7 13:14:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303567 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5EC3C47094 for ; Mon, 7 Jun 2021 13:14:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C1565610C7 for ; Mon, 7 Jun 2021 13:14:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230328AbhFGNQS (ORCPT ); Mon, 7 Jun 2021 09:16:18 -0400 Received: from mga06.intel.com ([134.134.136.31]:17596 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230322AbhFGNQR (ORCPT ); Mon, 7 Jun 2021 09:16:17 -0400 IronPort-SDR: pLAQcxNKA6gwSCzyA+k6f0rq8oMfRG1sY6VoZbXhg3FySiNxs5RqEy5cmm1arzFFO/GVsyU4OH 6NZQf9A4qteQ== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265773983" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265773983" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:25 -0700 IronPort-SDR: FpZ1FvGeOm6FXn4ByAUud7BHNXflla4ZULBicygVPDwbq1uzhM3jdYXpKLXdA4lHjwxHOsARQt Hxm/zMJUFgpA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881880" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:23 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/7] usb: typec: ucsi: Add poll worker for alternate modes Date: Mon, 7 Jun 2021 16:14:38 +0300 Message-Id: <20210607131442.20121-4-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org WIP. The alternate modes are now checked by polling them. That make's it possible to drop the huge delay for command completion timeout that we now have at least in the UCSI ACPI driver. The delay was causing other problems as the driver can't do anything for the connector until the command completes. In practice this is a "better" workaround for the problem where the firmware (PPM) does not return BUSY when it should with some commands. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 104 +++++++++++++++++++++++++++++++--- drivers/usb/typec/ucsi/ucsi.h | 1 + 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index a8e0e31dcddf5..d41147b3b6e8a 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -191,6 +191,62 @@ int ucsi_resume(struct ucsi *ucsi) EXPORT_SYMBOL_GPL(ucsi_resume); /* -------------------------------------------------------------------------- */ +struct ucsi_work { + struct work_struct work; + unsigned int count; + struct ucsi_connector *con; + int (*cb)(struct ucsi_connector *); +}; + +static void ucsi_poll_worker(struct work_struct *work) +{ + struct ucsi_work *uwork = container_of(work, struct ucsi_work, work); + struct ucsi_connector *con = uwork->con; + int ret; + + mutex_lock(&con->lock); + + if (!con->partner) { + mutex_unlock(&con->lock); + kfree(uwork); + return; + } + + ret = uwork->cb(con); + + if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) + queue_work(con->wq, &uwork->work); + else + kfree(uwork); + + mutex_unlock(&con->lock); +} + +static int ucsi_partner_task(struct ucsi_connector *con, + int (*cb)(struct ucsi_connector *), + int retries) +{ + struct ucsi_work *uwork; + + if (!con->partner) + return 0; + + uwork = kzalloc(sizeof(*uwork), GFP_KERNEL); + if (!uwork) + return -ENOMEM; + + INIT_WORK(&uwork->work, ucsi_poll_worker); + uwork->count = retries; + uwork->con = con; + uwork->cb = cb; + + queue_work(con->wq, &uwork->work); + + return 0; +} + +/* -------------------------------------------------------------------------- */ + void ucsi_altmode_update_active(struct ucsi_connector *con) { const struct typec_altmode *altmode = NULL; @@ -544,6 +600,25 @@ static void ucsi_get_src_pdos(struct ucsi_connector *con, int is_partner) con->num_pdos += ret / sizeof(u32); } +static int ucsi_check_altmodes(struct ucsi_connector *con) +{ + int ret; + + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); + if (ret && ret != -ETIMEDOUT) + dev_err(con->ucsi->dev, + "con%d: failed to register partner alt modes (%d)\n", + con->num, ret); + + /* Ignoring the errors in this case. */ + if (con->partner_altmode[0]) { + ucsi_altmode_update_active(con); + return 0; + } + + return ret; +} + static void ucsi_pwr_opmode_change(struct ucsi_connector *con) { switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { @@ -651,14 +726,7 @@ static void ucsi_partner_change(struct ucsi_connector *con) dev_err(con->ucsi->dev, "con:%d: failed to set usb role:%d\n", con->num, u_role); - /* Can't rely on Partner Flags field. Always checking the alt modes. */ - ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); - if (ret) - dev_err(con->ucsi->dev, - "con%d: failed to register partner alternate modes\n", - con->num); - else - ucsi_altmode_update_active(con); + ucsi_partner_task(con, ucsi_check_altmodes, 30); } static void ucsi_handle_connector_change(struct work_struct *work) @@ -1046,8 +1114,18 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) enum typec_accessory *accessory = cap->accessory; enum usb_role u_role = USB_ROLE_NONE; u64 command; + char *name; int ret; + name = kasprintf(GFP_KERNEL, "%s-con%d", dev_name(ucsi->dev), con->num); + if (!name) + return -ENOMEM; + + con->wq = create_singlethread_workqueue(name); + kfree(name); + if (!con->wq) + return -ENOMEM; + INIT_WORK(&con->work, ucsi_handle_connector_change); init_completion(&con->complete); mutex_init(&con->lock); @@ -1183,6 +1261,12 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) fwnode_handle_put(cap->fwnode); out_unlock: mutex_unlock(&con->lock); + + if (ret && con->wq) { + destroy_workqueue(con->wq); + con->wq = NULL; + } + return ret; } @@ -1253,6 +1337,8 @@ static int ucsi_init(struct ucsi *ucsi) ucsi_unregister_partner(con); ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); ucsi_unregister_port_psy(con); + if (con->wq) + destroy_workqueue(con->wq); typec_unregister_port(con->port); con->port = NULL; } @@ -1374,6 +1460,8 @@ void ucsi_unregister(struct ucsi *ucsi) ucsi_unregister_altmodes(&ucsi->connector[i], UCSI_RECIPIENT_CON); ucsi_unregister_port_psy(&ucsi->connector[i]); + if (ucsi->connector[i].wq) + destroy_workqueue(ucsi->connector[i].wq); typec_unregister_port(ucsi->connector[i].port); } diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index cee666790907e..d10b8c24435af 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -317,6 +317,7 @@ struct ucsi_connector { struct mutex lock; /* port lock */ struct work_struct work; struct completion complete; + struct workqueue_struct *wq; struct typec_port *port; struct typec_partner *partner; From patchwork Mon Jun 7 13:14:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303569 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82A56C47094 for ; Mon, 7 Jun 2021 13:14:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6AA65610FC for ; Mon, 7 Jun 2021 13:14:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230322AbhFGNQT (ORCPT ); Mon, 7 Jun 2021 09:16:19 -0400 Received: from mga06.intel.com ([134.134.136.31]:17596 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230333AbhFGNQS (ORCPT ); Mon, 7 Jun 2021 09:16:18 -0400 IronPort-SDR: lc0qqfZUu3xBbHgp+32IZ6hF0BoXBLHEcju3iMBmfe3N3H0/QyA/bA75/s6xZZLCy7VQUKHuYo JcbX/PqazQrg== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265773989" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265773989" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:27 -0700 IronPort-SDR: kPmwXhJBEIz3UawO9j7Cj1wmGv5P/SrYM6YsW+5S5f13lUeuW+20Psm6H6/N9PCutYTYI9jinV 7B6N8ZkeeEZg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881892" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:25 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 4/7] usb: typec: ucsi: acpi: Reduce the command completion timeout Date: Mon, 7 Jun 2021 16:14:39 +0300 Message-Id: <20210607131442.20121-5-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The huge delay was there to workaround a problem where the firmware did not report that if it was busy with the alternate mode commands. Now that the alternate modes are polled, the delay can be dropped. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 04976435ad736..6771f05e32c29 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, if (ret) goto out_clear_bit; - if (!wait_for_completion_timeout(&ua->complete, 60 * HZ)) + if (!wait_for_completion_timeout(&ua->complete, HZ)) ret = -ETIMEDOUT; out_clear_bit: From patchwork Mon Jun 7 13:14:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303571 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D58BFC47095 for ; Mon, 7 Jun 2021 13:14:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B629C610FC for ; Mon, 7 Jun 2021 13:14:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230374AbhFGNQX (ORCPT ); Mon, 7 Jun 2021 09:16:23 -0400 Received: from mga06.intel.com ([134.134.136.31]:17596 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230355AbhFGNQU (ORCPT ); Mon, 7 Jun 2021 09:16:20 -0400 IronPort-SDR: EsSwBZPwVOnRhC18zdMXUSJZYtnHTfrYYNlhgzyUrGtJGXRM/YaZyl6SItixAPqUdelBopqSry 0O7kC/cIhrIg== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265773995" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265773995" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:28 -0700 IronPort-SDR: d1xIPnGhVugxh0dThFVEoTGPZciorHsMAomRTUqDhB0/jQDAlWcw5vAmx5Zni2i5uo7NeIbvoq A2FNc8rxEMdg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881921" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:27 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 5/7] usb: typec: ucsi: Process every connector change as unique connector state Date: Mon, 7 Jun 2021 16:14:40 +0300 Message-Id: <20210607131442.20121-6-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This will change the Connector Change event handler function so that it will only read the connector status and store it as a unique state, queue a job where it's actually processed, and then acknowledge the event immediately. That routine will not do anything else from now on. That will make sure we don't loose any of the reported connector states even if they are reported while the driver is still processing the previous ones. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 177 ++++++++++++---------------------- drivers/usb/typec/ucsi/ucsi.h | 2 - 2 files changed, 61 insertions(+), 118 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index d41147b3b6e8a..a4123f77d1f16 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -49,11 +49,16 @@ static int ucsi_acknowledge_command(struct ucsi *ucsi) static int ucsi_acknowledge_connector_change(struct ucsi *ucsi) { u64 ctrl; + int ret; ctrl = UCSI_ACK_CC_CI; ctrl |= UCSI_ACK_CONNECTOR_CHANGE; - return ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); + mutex_lock(&ucsi->ppm_lock); + ret = ucsi->ops->sync_write(ucsi, UCSI_CONTROL, &ctrl, sizeof(ctrl)); + mutex_unlock(&ucsi->ppm_lock); + + return ret; } static int ucsi_exec_command(struct ucsi *ucsi, u64 command); @@ -729,118 +734,26 @@ static void ucsi_partner_change(struct ucsi_connector *con) ucsi_partner_task(con, ucsi_check_altmodes, 30); } -static void ucsi_handle_connector_change(struct work_struct *work) +struct ucsi_con_event { + struct work_struct work; + struct ucsi_connector *con; + struct ucsi_connector_status status; +}; + +static void ucsi_connector_work(struct work_struct *work) { - struct ucsi_connector *con = container_of(work, struct ucsi_connector, - work); + struct ucsi_con_event *event = container_of(work, struct ucsi_con_event, work); + struct ucsi_connector *con = event->con; struct ucsi *ucsi = con->ucsi; - struct ucsi_connector_status pre_ack_status; - struct ucsi_connector_status post_ack_status; enum typec_role role; enum usb_role u_role = USB_ROLE_NONE; - u16 inferred_changes; - u16 changed_flags; - u64 command; int ret; mutex_lock(&con->lock); - /* - * Some/many PPMs have an issue where all fields in the change bitfield - * are cleared when an ACK is send. This will causes any change - * between GET_CONNECTOR_STATUS and ACK to be lost. - * - * We work around this by re-fetching the connector status afterwards. - * We then infer any changes that we see have happened but that may not - * be represented in the change bitfield. - * - * Also, even though we don't need to know the currently supported alt - * modes, we run the GET_CAM_SUPPORTED command to ensure the PPM does - * not get stuck in case it assumes we do. - * Always do this, rather than relying on UCSI_CONSTAT_CAM_CHANGE to be - * set in the change bitfield. - * - * We end up with the following actions: - * 1. UCSI_GET_CONNECTOR_STATUS, store result, update unprocessed_changes - * 2. UCSI_GET_CAM_SUPPORTED, discard result - * 3. ACK connector change - * 4. UCSI_GET_CONNECTOR_STATUS, store result - * 5. Infere lost changes by comparing UCSI_GET_CONNECTOR_STATUS results - * 6. If PPM reported a new change, then restart in order to ACK - * 7. Process everything as usual. - * - * We may end up seeing a change twice, but we can only miss extremely - * short transitional changes. - */ - - /* 1. First UCSI_GET_CONNECTOR_STATUS */ - command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); - ret = ucsi_send_command(ucsi, command, &pre_ack_status, - sizeof(pre_ack_status)); - if (ret < 0) { - dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", - __func__, ret); - goto out_unlock; - } - con->unprocessed_changes |= pre_ack_status.change; - - /* 2. Run UCSI_GET_CAM_SUPPORTED and discard the result. */ - command = UCSI_GET_CAM_SUPPORTED; - command |= UCSI_CONNECTOR_NUMBER(con->num); - ucsi_send_command(con->ucsi, command, NULL, 0); - - /* 3. ACK connector change */ - ret = ucsi_acknowledge_connector_change(ucsi); - clear_bit(EVENT_PENDING, &ucsi->flags); - if (ret) { - dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); - goto out_unlock; - } - - /* 4. Second UCSI_GET_CONNECTOR_STATUS */ - command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); - ret = ucsi_send_command(ucsi, command, &post_ack_status, - sizeof(post_ack_status)); - if (ret < 0) { - dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", - __func__, ret); - goto out_unlock; - } - - /* 5. Inferre any missing changes */ - changed_flags = pre_ack_status.flags ^ post_ack_status.flags; - inferred_changes = 0; - if (UCSI_CONSTAT_PWR_OPMODE(changed_flags) != 0) - inferred_changes |= UCSI_CONSTAT_POWER_OPMODE_CHANGE; - - if (changed_flags & UCSI_CONSTAT_CONNECTED) - inferred_changes |= UCSI_CONSTAT_CONNECT_CHANGE; - - if (changed_flags & UCSI_CONSTAT_PWR_DIR) - inferred_changes |= UCSI_CONSTAT_POWER_DIR_CHANGE; - - if (UCSI_CONSTAT_PARTNER_FLAGS(changed_flags) != 0) - inferred_changes |= UCSI_CONSTAT_PARTNER_CHANGE; - - if (UCSI_CONSTAT_PARTNER_TYPE(changed_flags) != 0) - inferred_changes |= UCSI_CONSTAT_PARTNER_CHANGE; - - /* Mask out anything that was correctly notified in the later call. */ - inferred_changes &= ~post_ack_status.change; - if (inferred_changes) - dev_dbg(ucsi->dev, "%s: Inferred changes that would have been lost: 0x%04x\n", - __func__, inferred_changes); - - con->unprocessed_changes |= inferred_changes; - - /* 6. If PPM reported a new change, then restart in order to ACK */ - if (post_ack_status.change) - goto out_unlock; - - /* 7. Continue as if nothing happened */ - con->status = post_ack_status; - con->status.change = con->unprocessed_changes; - con->unprocessed_changes = 0; + trace_ucsi_connector_change(con->num, &event->status); + con->status = event->status; + kfree(event); role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); @@ -898,17 +811,49 @@ static void ucsi_handle_connector_change(struct work_struct *work) if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) ucsi_partner_change(con); - trace_ucsi_connector_change(con->num, &con->status); + mutex_unlock(&con->lock); +} -out_unlock: - if (test_and_clear_bit(EVENT_PENDING, &ucsi->flags)) { - schedule_work(&con->work); - mutex_unlock(&con->lock); - return; +/* + * We can not read the connector status in ucsi_connector_change() function + * below because there may be already a command pending. This work is scheduled + * separately only because of that. + * + * This function must finish fast so we do not loose the next events. Every + * event will have a separate job queued for it in the connector specific + * workqueue. That way the next event can be generated safely before the + * previous ones are fully processed. + */ +static void ucsi_handle_connector_change(struct work_struct *work) +{ + struct ucsi_connector *con = container_of(work, struct ucsi_connector, work); + struct ucsi_connector_status status; + struct ucsi_con_event *event; + u64 command; + int ret; + + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); + ret = ucsi_send_command(con->ucsi, command, &status, sizeof(status)); + if (ret < 0) { + dev_err(con->ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n", ret); + goto out_ack; } - clear_bit(EVENT_PROCESSING, &ucsi->flags); - mutex_unlock(&con->lock); + event = kzalloc(sizeof(*event), GFP_KERNEL); + if (!event) + goto out_ack; + + INIT_WORK(&event->work, ucsi_connector_work); + event->status = status; + event->con = con; + queue_work(con->wq, &event->work); + +out_ack: + clear_bit(EVENT_PENDING, &con->ucsi->flags); + + ret = ucsi_acknowledge_connector_change(con->ucsi); + if (ret) + dev_err(con->ucsi->dev, "%s: ACK failed (%d)", __func__, ret); } /** @@ -925,10 +870,10 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num) return; } - set_bit(EVENT_PENDING, &ucsi->flags); + if (test_and_set_bit(EVENT_PENDING, &ucsi->flags)) + return; - if (!test_and_set_bit(EVENT_PROCESSING, &ucsi->flags)) - schedule_work(&con->work); + schedule_work(&con->work); } EXPORT_SYMBOL_GPL(ucsi_connector_change); diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index d10b8c24435af..280f1e1bda2c9 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -300,7 +300,6 @@ struct ucsi { #define EVENT_PENDING 0 #define COMMAND_PENDING 1 #define ACK_PENDING 2 -#define EVENT_PROCESSING 3 }; #define UCSI_MAX_SVID 5 @@ -327,7 +326,6 @@ struct ucsi_connector { struct typec_capability typec_cap; - u16 unprocessed_changes; struct ucsi_connector_status status; struct ucsi_connector_capability cap; struct power_supply *psy; From patchwork Mon Jun 7 13:14:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303573 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6AF96C47094 for ; Mon, 7 Jun 2021 13:14:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5192E610FC for ; Mon, 7 Jun 2021 13:14:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230383AbhFGNQY (ORCPT ); Mon, 7 Jun 2021 09:16:24 -0400 Received: from mga06.intel.com ([134.134.136.31]:17614 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230333AbhFGNQW (ORCPT ); Mon, 7 Jun 2021 09:16:22 -0400 IronPort-SDR: mk52y3lIzpqqsuxivELXE7AesZGZ2IzfASfzT17nQpkAfDQH7ATeBeQbORLXrgZk3EJ5NgesMY ht2d/ES7jGSA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265774000" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265774000" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:30 -0700 IronPort-SDR: G7vQsWiA/NyYqrg2pxgdz/zVX2MYeCaZWAhQdACyfC0c62EV/Y7wao2mn4wX2QZbkaSc/g7moF 9FkRONsaikdw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881931" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:29 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 6/7] usb: typec: ucsi: Filter out spurious events Date: Mon, 7 Jun 2021 16:14:41 +0300 Message-Id: <20210607131442.20121-7-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Ignoring events without changes. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index a4123f77d1f16..ce80a433ef9db 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -839,6 +839,11 @@ static void ucsi_handle_connector_change(struct work_struct *work) goto out_ack; } + if (!status.change) { + dev_dbg(con->ucsi->dev, "con%d: spurious event\n", con->num); + goto out_ack; + } + event = kzalloc(sizeof(*event), GFP_KERNEL); if (!event) goto out_ack; From patchwork Mon Jun 7 13:14:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 12303575 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23754C48BCD for ; Mon, 7 Jun 2021 13:14:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F76661159 for ; Mon, 7 Jun 2021 13:14:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230381AbhFGNQZ (ORCPT ); Mon, 7 Jun 2021 09:16:25 -0400 Received: from mga06.intel.com ([134.134.136.31]:17618 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230387AbhFGNQY (ORCPT ); Mon, 7 Jun 2021 09:16:24 -0400 IronPort-SDR: dCwrKBJ0c0PCZ4pvMPHC1GzeYYB3pL718ybTaNqlJ4VpjCXGgZ1XykMELYgPAp6GFgXyQT1uF6 L+KIzV3J3Nfg== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="265774005" X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="265774005" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jun 2021 06:14:32 -0700 IronPort-SDR: pHPpuAua0PGlmofypaEQtqRyUBiLx9Bh2yT/VCqntBYmkGlo/BWPzwOb0LFE8y/rkZ8ESLV2xM pSF7H+dmzS+w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,255,1616482800"; d="scan'208";a="551881939" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 07 Jun 2021 06:14:31 -0700 From: Heikki Krogerus To: Benjamin Berg Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 7/7] usb: typec: ucsi: Read the PDOs in separate work Date: Mon, 7 Jun 2021 16:14:42 +0300 Message-Id: <20210607131442.20121-8-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> References: <20210607131442.20121-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Polling also the PDOs, just like the alt modes. After this ucsi_handle_connector_change() doesn't execute any commands. Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index ce80a433ef9db..bd39fe2cb1d0b 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -575,7 +575,7 @@ static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner, command |= UCSI_GET_PDOS_SRC_PDOS; ret = ucsi_send_command(ucsi, command, pdos + offset, num_pdos * sizeof(u32)); - if (ret < 0) + if (ret < 0 && ret != -ETIMEDOUT) dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); if (ret == 0 && offset == 0) dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n"); @@ -583,26 +583,30 @@ static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner, return ret; } -static void ucsi_get_src_pdos(struct ucsi_connector *con, int is_partner) +static int ucsi_get_src_pdos(struct ucsi_connector *con) { int ret; /* UCSI max payload means only getting at most 4 PDOs at a time */ ret = ucsi_get_pdos(con, 1, con->src_pdos, 0, UCSI_MAX_PDOS); if (ret < 0) - return; + return ret; con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */ if (con->num_pdos < UCSI_MAX_PDOS) - return; + return 0; /* get the remaining PDOs, if any */ ret = ucsi_get_pdos(con, 1, con->src_pdos, UCSI_MAX_PDOS, PDO_MAX_OBJECTS - UCSI_MAX_PDOS); if (ret < 0) - return; + return ret; con->num_pdos += ret / sizeof(u32); + + ucsi_port_psy_changed(con); + + return 0; } static int ucsi_check_altmodes(struct ucsi_connector *con) @@ -630,7 +634,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con) case UCSI_CONSTAT_PWR_OPMODE_PD: con->rdo = con->status.request_data_obj; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD); - ucsi_get_src_pdos(con, 1); + ucsi_partner_task(con, ucsi_get_src_pdos, 20); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: con->rdo = 0; @@ -758,10 +762,8 @@ static void ucsi_connector_work(struct work_struct *work) role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE || - con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) { + con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) ucsi_pwr_opmode_change(con); - ucsi_port_psy_changed(con); - } if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) { typec_set_pwr_role(con->port, role); @@ -1170,9 +1172,9 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) if (con->status.flags & UCSI_CONSTAT_CONNECTED) { typec_set_pwr_role(con->port, !!(con->status.flags & UCSI_CONSTAT_PWR_DIR)); - ucsi_pwr_opmode_change(con); ucsi_register_partner(con); ucsi_port_psy_changed(con); + ucsi_pwr_opmode_change(con); } con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode);