From patchwork Thu Feb 4 04:10:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 12066277 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 BD389C433E0 for ; Thu, 4 Feb 2021 04:11:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 75F0464DFA for ; Thu, 4 Feb 2021 04:11:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231622AbhBDELl (ORCPT ); Wed, 3 Feb 2021 23:11:41 -0500 Received: from smtprelay-out1.synopsys.com ([149.117.87.133]:37100 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231499AbhBDELk (ORCPT ); Wed, 3 Feb 2021 23:11:40 -0500 Received: from mailhost.synopsys.com (sv1-mailhost1.synopsys.com [10.205.2.131]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id DC2FCC010B; Thu, 4 Feb 2021 04:10:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1612411838; bh=ojvkj62zAfzpBqj9y67MlTXgb83sFwP1MqYNI9jHJ+Y=; h=Date:In-Reply-To:References:From:Subject:To:From; b=bf7N02msf47J8JT697pxbwTE3FOX6pqXCnXp6nEbKhaU+LudhuEEgmgFBLgTsHY0o gfGkSc0+9epeGWSCuoPH2enXynXz1vDIB0orDEsjcWs9eN+Ret8CWxXUb5TRiLSTx9 dyVObIM9VjaK90hQ5m8ekuh3vjQfVr9022FEiD2B4hoOu5x4r8EYI3cuAfZXxr1OyZ gTXXeQCdO5unJkD+JA/bCxKUDBh+rYibwk5hDNRGBbfssCGLThqBbyTOhITk1GUswd AhF19rH6qX+lfKlvGRVddsgjlrgnP9NRCks28PDVIhNo2b4RICfkkCT7GzAG3ZfsUS qqUGiKltBU5xQ== Received: from te-lab16 (unknown [10.10.52.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id E922CA0068; Thu, 4 Feb 2021 04:10:33 +0000 (UTC) Received: by te-lab16 (sSMTP sendmail emulation); Wed, 03 Feb 2021 20:10:33 -0800 Date: Wed, 03 Feb 2021 20:10:33 -0800 Message-Id: <28b2ea855b86a0754548c636093784bbc0657c05.1612410491.git.Thinh.Nguyen@synopsys.com> In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH v2 1/8] usb: core: Track SuperSpeed Plus GenXxY To: Greg Kroah-Hartman , Thinh.Nguyen@synopsys.com, linux-usb@vger.kernel.org, Andrey Konovalov , Alan Stern , Eugeniu Rosca , Hardik Gajjar , "Gustavo A. R. Silva" , Dmitry Vyukov , Allen Pais , Oliver Neukum , Sebastian Andrzej Siewior , "Ahmed S. Darwish" Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Introduce ssp_rate field to usb_device structure to capture the connected SuperSpeed Plus signaling rate generation and lane count with the corresponding usb_ssp_rate enum. Signed-off-by: Thinh Nguyen --- Changes in v2: - None drivers/usb/core/hcd.c | 6 +++- drivers/usb/core/hub.c | 78 ++++++++++++++++++++++++++++++++++++++++++ include/linux/usb.h | 2 ++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ad5a0f405a75..55de04df3022 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2721,6 +2721,7 @@ int usb_add_hcd(struct usb_hcd *hcd, rhdev->rx_lanes = 1; rhdev->tx_lanes = 1; + rhdev->ssp_rate = USB_SSP_GEN_UNKNOWN; switch (hcd->speed) { case HCD_USB11: @@ -2738,8 +2739,11 @@ int usb_add_hcd(struct usb_hcd *hcd, case HCD_USB32: rhdev->rx_lanes = 2; rhdev->tx_lanes = 2; - fallthrough; + rhdev->ssp_rate = USB_SSP_GEN_2x2; + rhdev->speed = USB_SPEED_SUPER_PLUS; + break; case HCD_USB31: + rhdev->ssp_rate = USB_SSP_GEN_2x1; rhdev->speed = USB_SPEED_SUPER_PLUS; break; default: diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7f71218cc1e5..e78b2dd7801a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -2668,6 +2669,81 @@ int usb_authorize_device(struct usb_device *usb_dev) return result; } +/** + * get_port_ssp_rate - Match the extended port status to SSP rate + * @hdev: The hub device + * @ext_portstatus: extended port status + * + * Match the extended port status speed id to the SuperSpeed Plus sublink speed + * capability attributes. Base on the number of connected lanes and speed, + * return the corresponding enum usb_ssp_rate. + */ +static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev, + u32 ext_portstatus) +{ + struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap; + u32 attr; + u8 speed_id; + u8 ssac; + u8 lanes; + int i; + + if (!ssp_cap) + goto out; + + speed_id = ext_portstatus & USB_EXT_PORT_STAT_RX_SPEED_ID; + lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; + + ssac = le32_to_cpu(ssp_cap->bmAttributes) & + USB_SSP_SUBLINK_SPEED_ATTRIBS; + + for (i = 0; i <= ssac; i++) { + u8 ssid; + + attr = le32_to_cpu(ssp_cap->bmSublinkSpeedAttr[i]); + ssid = FIELD_GET(USB_SSP_SUBLINK_SPEED_SSID, attr); + if (speed_id == ssid) { + u16 mantissa; + u8 lse; + u8 type; + + /* + * Note: currently asymmetric lane types are only + * applicable for SSIC operate in SuperSpeed protocol + */ + type = FIELD_GET(USB_SSP_SUBLINK_SPEED_ST, attr); + if (type == USB_SSP_SUBLINK_SPEED_ST_ASYM_RX || + type == USB_SSP_SUBLINK_SPEED_ST_ASYM_TX) + goto out; + + if (FIELD_GET(USB_SSP_SUBLINK_SPEED_LP, attr) != + USB_SSP_SUBLINK_SPEED_LP_SSP) + goto out; + + lse = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSE, attr); + mantissa = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSM, attr); + + /* Convert to Gbps */ + for (; lse < USB_SSP_SUBLINK_SPEED_LSE_GBPS; lse++) + mantissa /= 1000; + + if (mantissa >= 10 && lanes == 1) + return USB_SSP_GEN_2x1; + + if (mantissa >= 10 && lanes == 2) + return USB_SSP_GEN_2x2; + + if (mantissa >= 5 && lanes == 2) + return USB_SSP_GEN_1x2; + + goto out; + } + } + +out: + return USB_SSP_GEN_UNKNOWN; +} + /* * Return 1 if port speed is SuperSpeedPlus, 0 otherwise * check it from the link protocol field of the current speed ID attribute. @@ -2850,9 +2926,11 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, /* extended portstatus Rx and Tx lane count are zero based */ udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1; + udev->ssp_rate = get_port_ssp_rate(hub->hdev, ext_portstatus); } else { udev->rx_lanes = 1; udev->tx_lanes = 1; + udev->ssp_rate = USB_SSP_GEN_UNKNOWN; } if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; diff --git a/include/linux/usb.h b/include/linux/usb.h index 7d72c4e0713c..c334387f950e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -560,6 +560,7 @@ struct usb3_lpm_parameters { * @speed: device speed: high/full/low (or error) * @rx_lanes: number of rx lanes in use, USB 3.2 adds dual-lane support * @tx_lanes: number of tx lanes in use, USB 3.2 adds dual-lane support + * @ssp_rate: SuperSpeed Plus phy signaling rate and lane count * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub * @ttport: device port on that tt hub * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints @@ -636,6 +637,7 @@ struct usb_device { enum usb_device_speed speed; unsigned int rx_lanes; unsigned int tx_lanes; + enum usb_ssp_rate ssp_rate; struct usb_tt *tt; int ttport;