From patchwork Thu Feb 29 14:14:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577167 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3689A12F38D for ; Thu, 29 Feb 2024 14:13:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215989; cv=none; b=XgSK20+LGckZD7Jt+Om9Oz3TOdjLDzyyCW5A9ViYdXbI/Eu77sJEuNqGpNER8Xh+2nkDocBJUg31yUpRWY8SMjbpdzEPWr+GJr0o2YpJkFe23LBSAxfG8IMbvz5oZ7CuB9h2a80vDPtBgMv5enp9wr0w/5TzHLuaY3Q5vuM4V0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215989; c=relaxed/simple; bh=rN22wtC2AcLBosJ4fRQiGBqLV8WQo4mkfmRparUml+Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AJcJwQrJlOsGiMfMATMCHpEadrgPPpNeTUKIC8sPe4eBHPbCYlMJ/wOZJFd0RB4x0DXwAT5scX6DNH8wq/U4rPBsUDQGq+sq1xDOlztx1JJclQcrs8OTXH+5ox3sptr0HIiedwssY1CxZIsBTJWhF4DC37BZ/ldgN7dTqpC4P6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=F5qfnrlv; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="F5qfnrlv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215988; x=1740751988; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rN22wtC2AcLBosJ4fRQiGBqLV8WQo4mkfmRparUml+Q=; b=F5qfnrlvB45Lcb00EX8BiUm7L9Su9gIruhGu/Qo/FHSVaZbo+g8FMDYt bflM5Vbp4MEx1mOpz1dfdlmvlJBHbFTMh57UJQnnlQoX7C7bMIhtSf1ZC W0U6V/1/eMWCUBN9RMOYUfEqExfkICTPg+3l8d6+PruYur/Ys89tdJ9n3 SQMaLyUkL1zI+WN/9tavyCmGJ/+ELusNHEplY/zYiYfBPAAp7vG7ECGd2 a5H2typIBQAl6wZNLQJo4W+3jaxHFxvdt+XT1/BifDTGM0PVdjGZl1IQr OkZQEbSkVqIcEyYKJbqRkU4ofj4gnGARmRxv9Z/YD+7rQQUT87ycBb00i A==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609367" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609367" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:07 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035983" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035983" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:05 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Niklas Neronin , Mathias Nyman Subject: [PATCH 1/9] xhci: rework how real & fake ports are found Date: Thu, 29 Feb 2024 16:14:30 +0200 Message-Id: <20240229141438.619372-2-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Niklas Neronin xHC hardware needs to know which roothub port a USB device is attached to when controlling the device, so the xHCI driver stores in each device the roothub port which it's connected behind. This is done with two different port index values, the 'real_port' which is an index to the xHC hardware port register array, and the 'fake_port' which is the per hub port index used by the hub driver. Instead of finding real & fake port separately, find the root hub port 'xhci_port' structure which contains both real & fake port values: - 'real_port' is ('hw_portnum' + 1) - 'fake_port' is ('hcd_portnum' + 1) i.e. real & fake port are 'hw_portnum' & 'hcd_portnum' in one-based format. The 'xhci_port' structure is a better way to refer to roothub ports than the 'real_port' & 'fake_port'. As a result, these port indexes are slated to be replaced with a direct pointer to the root hub port. This patch setups the ground work for the future changes. Signed-off-by: Niklas Neronin Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-mem.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 450adaca68ee..92160b96d4c0 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1051,16 +1051,16 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * The xHCI roothub may have ports of differing speeds in any order in the port * status registers. * - * The xHCI hardware wants to know the roothub port number that the USB device + * The xHCI hardware wants to know the roothub port that the USB device * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status - * registers. Call xhci_find_raw_port_number() to get real index. + * registers. */ -static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, - struct usb_device *udev) +static struct xhci_port *xhci_find_rhub_port(struct xhci_hcd *xhci, struct usb_device *udev) { struct usb_device *top_dev; + struct xhci_hub *rhub; struct usb_hcd *hcd; if (udev->speed >= USB_SPEED_SUPER) @@ -1072,7 +1072,8 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, top_dev = top_dev->parent) /* Found device below root hub */; - return xhci_find_raw_port_number(hcd, top_dev->portnum); + rhub = xhci_get_rhub(hcd); + return rhub->ports[top_dev->portnum - 1]; } /* Setup an xHCI virtual device for a Set Address command */ @@ -1081,9 +1082,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud struct xhci_virt_device *dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; - u32 port_num; + struct xhci_port *rhub_port; u32 max_packets; - struct usb_device *top_dev; dev = xhci->devs[udev->slot_id]; /* Slot ID 0 is reserved */ @@ -1124,17 +1124,13 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud return -EINVAL; } /* Find the root hub port this device is under */ - port_num = xhci_find_real_port_number(xhci, udev); - if (!port_num) + rhub_port = xhci_find_rhub_port(xhci, udev); + if (!rhub_port) return -EINVAL; - slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(port_num)); - /* Set the port number in the virtual_device to the faked port number */ - for (top_dev = udev; top_dev->parent && top_dev->parent->parent; - top_dev = top_dev->parent) - /* Found device below root hub */; - dev->fake_port = top_dev->portnum; - dev->real_port = port_num; - xhci_dbg(xhci, "Set root hub portnum to %d\n", port_num); + dev->real_port = rhub_port->hw_portnum + 1; + dev->fake_port = rhub_port->hcd_portnum + 1; + slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->real_port)); + xhci_dbg(xhci, "Set root hub portnum to %d\n", dev->real_port); xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->fake_port); /* Find the right bandwidth table that this device will be a part of. @@ -1144,12 +1140,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud * will never be created for the HS root hub. */ if (!udev->tt || !udev->tt->hub->parent) { - dev->bw_table = &xhci->rh_bw[port_num - 1].bw_table; + dev->bw_table = &xhci->rh_bw[dev->real_port - 1].bw_table; } else { struct xhci_root_port_bw_info *rh_bw; struct xhci_tt_bw_info *tt_bw; - rh_bw = &xhci->rh_bw[port_num - 1]; + rh_bw = &xhci->rh_bw[dev->real_port - 1]; /* Find the right TT. */ list_for_each_entry(tt_bw, &rh_bw->tts, tt_list) { if (tt_bw->slot_id != udev->tt->hub->slot_id) From patchwork Thu Feb 29 14:14:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577168 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E1AE12A177 for ; Thu, 29 Feb 2024 14:13:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215991; cv=none; b=bkF1eJLmJAVZpXGVWMK4qW12IKzJh8Jd8slkQic3G/X73PspXFnni01PQjKDfI+D9hU6BBnXbCsOlUbeIptNln3+/CISjSUFN3M+A3uxqeDxe2g5o5cdJsJqlXtr4avyoBtXRKxSXwhwGLXnxaxOhVj5ZxIT9KeUGiopoT4noV0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215991; c=relaxed/simple; bh=/EKJKs02pVphNe/UyDJk13umb2YvfrxKd4pVLTli0os=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eM2DjHDRoC99oqBprV2cDgBd3og12NmzT51JiJTHe053rc/6MqwtgDOGAaEWB9YrcPhqalfaaiv7BIPmx6f2i1+HLCQIOXY+WepyuUCi0Oe73tdp798FnLe0OLn/z/qzBB9v9WqssjhhQKrbsSMXuIEZ+cr4kIFic2ybWAXIMo0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=P5lMCfxh; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="P5lMCfxh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215989; x=1740751989; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/EKJKs02pVphNe/UyDJk13umb2YvfrxKd4pVLTli0os=; b=P5lMCfxhb35Z8JPDwOF/UyLgcGDqV3uWwXJzED7Hq1lJ7LrsDQ7RaRZ4 ukq62eWkBdSpb15FGdSnz8HoPfokxep+qgsSARH6yGe6TIw2899rCt4hl eKa8/PwnOuP8eWBp1cC6O44Ecd1jU6DYewTgHkp+gc+MTWuY+V6MOQYlA JINVF8aAfZGZBKYADuUZxxYVDK7qCEZMraywaKHAtXcW0QHa6l3C0nkwI JYgsYWhY4yHJgUW/VdrZkzh1NelV5wGG+7YmlA59Tn0omeCNdVL2KAHG7 w+W9qQg1oaFGu4Ie0u2cvlhwh4/wOBEqH9vexnxOkQKKzuh/mX7+suJDE w==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609372" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609372" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035986" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035986" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:07 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Niklas Neronin , Mathias Nyman Subject: [PATCH 2/9] xhci: replace real & fake port with pointer to root hub port Date: Thu, 29 Feb 2024 16:14:31 +0200 Message-Id: <20240229141438.619372-3-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Niklas Neronin Variables real & fake port do not convey their purpose, thus they are replaced with a pointer to the root hub port 'struct xhci_port *rhub_port'. 'rhub_port' contains real & fake ports in zero-based format, which happens to be more widely used inside the xHCI driver: - 'real_port' is ('rhub_port->hw_portnum' + 1) - 'fake_port' is ('rhub_port->hcd_portnum' + 1) One reason for real port being one-based, is to signal other functions in case struct 'xhci_virt_device' initialization failed, in this case the value will remain 0. This is no longer needed, instead we check whether or not 'rhub_port' is 'NULL'. Signed-off-by: Niklas Neronin Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-hub.c | 4 +++- drivers/usb/host/xhci-mem.c | 35 ++++++++++++++------------------- drivers/usb/host/xhci-mtk-sch.c | 14 +++++-------- drivers/usb/host/xhci-trace.h | 12 +++++------ drivers/usb/host/xhci.c | 12 +++++------ drivers/usb/host/xhci.h | 3 +-- 6 files changed, 35 insertions(+), 45 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0980ade2a234..37128a777a58 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -464,13 +464,15 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, int i; enum usb_device_speed speed; + /* 'hcd_portnum' is zero-based, thus convert one-based 'port' to zero-based */ + port -= 1; slot_id = 0; for (i = 0; i < MAX_HC_SLOTS; i++) { if (!xhci->devs[i] || !xhci->devs[i]->udev) continue; speed = xhci->devs[i]->udev->speed; if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3)) - && xhci->devs[i]->fake_port == port) { + && xhci->devs[i]->rhub_port->hcd_portnum == port) { slot_id = i; break; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 92160b96d4c0..9fa68fa17ac7 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -789,15 +789,14 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, bool slot_found = false; /* If the device never made it past the Set Address stage, - * it may not have the real_port set correctly. + * it may not have the root hub port pointer set correctly. */ - if (virt_dev->real_port == 0 || - virt_dev->real_port > HCS_MAX_PORTS(xhci->hcs_params1)) { - xhci_dbg(xhci, "Bad real port.\n"); + if (!virt_dev->rhub_port) { + xhci_dbg(xhci, "Bad rhub port.\n"); return; } - tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts); + tt_list_head = &(xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts); list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { /* Multi-TT hubs will have more than one entry */ if (tt_info->slot_id == slot_id) { @@ -834,7 +833,7 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, goto free_tts; INIT_LIST_HEAD(&tt_info->tt_list); list_add(&tt_info->tt_list, - &xhci->rh_bw[virt_dev->real_port - 1].tts); + &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].tts); tt_info->slot_id = virt_dev->udev->slot_id; if (tt->multi) tt_info->ttport = i+1; @@ -929,13 +928,12 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i if (!vdev) return; - if (vdev->real_port == 0 || - vdev->real_port > HCS_MAX_PORTS(xhci->hcs_params1)) { - xhci_dbg(xhci, "Bad vdev->real_port.\n"); + if (!vdev->rhub_port) { + xhci_dbg(xhci, "Bad rhub port.\n"); goto out; } - tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts); + tt_list_head = &(xhci->rh_bw[vdev->rhub_port->hw_portnum].tts); list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { /* is this a hub device that added a tt_info to the tts list */ if (tt_info->slot_id == slot_id) { @@ -1082,7 +1080,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud struct xhci_virt_device *dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; - struct xhci_port *rhub_port; u32 max_packets; dev = xhci->devs[udev->slot_id]; @@ -1124,14 +1121,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud return -EINVAL; } /* Find the root hub port this device is under */ - rhub_port = xhci_find_rhub_port(xhci, udev); - if (!rhub_port) + dev->rhub_port = xhci_find_rhub_port(xhci, udev); + if (!dev->rhub_port) return -EINVAL; - dev->real_port = rhub_port->hw_portnum + 1; - dev->fake_port = rhub_port->hcd_portnum + 1; - slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->real_port)); - xhci_dbg(xhci, "Set root hub portnum to %d\n", dev->real_port); - xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->fake_port); + slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->rhub_port->hw_portnum + 1)); + xhci_dbg(xhci, "Slot ID %d: HW portnum %d, hcd portnum %d\n", + udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum); /* Find the right bandwidth table that this device will be a part of. * If this is a full speed device attached directly to a root port (or a @@ -1140,12 +1135,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud * will never be created for the HS root hub. */ if (!udev->tt || !udev->tt->hub->parent) { - dev->bw_table = &xhci->rh_bw[dev->real_port - 1].bw_table; + dev->bw_table = &xhci->rh_bw[dev->rhub_port->hw_portnum].bw_table; } else { struct xhci_root_port_bw_info *rh_bw; struct xhci_tt_bw_info *tt_bw; - rh_bw = &xhci->rh_bw[dev->real_port - 1]; + rh_bw = &xhci->rh_bw[dev->rhub_port->hw_portnum]; /* Find the right TT. */ list_for_each_entry(tt_bw, &rh_bw->tts, tt_list) { if (tt_bw->slot_id != udev->tt->hub->slot_id) diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index 61f3f8bbdcea..27eb384a3963 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -122,10 +122,6 @@ static u32 get_bw_boundary(enum usb_device_speed speed) * each HS root port is treated as a single bandwidth domain, * but each SS root port is treated as two bandwidth domains, one for IN eps, * one for OUT eps. -* @real_port value is defined as follow according to xHCI spec: -* 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc -* so the bandwidth domain array is organized as follow for simplification: -* SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY */ static struct mu3h_sch_bw_info * get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev, @@ -136,19 +132,19 @@ get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev, int bw_index; virt_dev = xhci->devs[udev->slot_id]; - if (!virt_dev->real_port) { - WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev)); + if (!virt_dev->rhub_port) { + WARN_ONCE(1, "%s invalid rhub port\n", dev_name(&udev->dev)); return NULL; } if (udev->speed >= USB_SPEED_SUPER) { if (usb_endpoint_dir_out(&ep->desc)) - bw_index = (virt_dev->real_port - 1) * 2; + bw_index = (virt_dev->rhub_port->hw_portnum) * 2; else - bw_index = (virt_dev->real_port - 1) * 2 + 1; + bw_index = (virt_dev->rhub_port->hw_portnum) * 2 + 1; } else { /* add one more for each SS port */ - bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1; + bw_index = virt_dev->rhub_port->hw_portnum + xhci->usb3_rhub.num_ports; } return &mtk->sch_array[bw_index]; diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index ac47b1c0544a..1740000d54c2 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -172,8 +172,8 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __field(void *, vdev) __field(unsigned long long, out_ctx) __field(unsigned long long, in_ctx) - __field(u8, fake_port) - __field(u8, real_port) + __field(int, hcd_portnum) + __field(int, hw_portnum) __field(u16, current_mel) ), @@ -181,13 +181,13 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __entry->vdev = vdev; __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma; __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma; - __entry->fake_port = (u8) vdev->fake_port; - __entry->real_port = (u8) vdev->real_port; + __entry->hcd_portnum = (int) vdev->rhub_port->hcd_portnum; + __entry->hw_portnum = (int) vdev->rhub_port->hw_portnum; __entry->current_mel = (u16) vdev->current_mel; ), - TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d", + TP_printk("vdev %p ctx %llx | %llx hcd_portnum %d hw_portnum %d current_mel %d", __entry->vdev, __entry->in_ctx, __entry->out_ctx, - __entry->fake_port, __entry->real_port, __entry->current_mel + __entry->hcd_portnum, __entry->hw_portnum, __entry->current_mel ) ); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b405b8236134..c50d5881e214 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2273,7 +2273,7 @@ static int xhci_check_tt_bw_table(struct xhci_hcd *xhci, struct xhci_tt_bw_info *tt_info; /* Find the bandwidth table for the root port this TT is attached to. */ - bw_table = &xhci->rh_bw[virt_dev->real_port - 1].bw_table; + bw_table = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum].bw_table; tt_info = virt_dev->tt_info; /* If this TT already had active endpoints, the bandwidth for this TT * has already been added. Removing all periodic endpoints (and thus @@ -2391,7 +2391,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, if (virt_dev->tt_info) { xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Recalculating BW for rootport %u", - virt_dev->real_port); + virt_dev->rhub_port->hw_portnum + 1); if (xhci_check_tt_bw_table(xhci, virt_dev, old_active_eps)) { xhci_warn(xhci, "Not enough bandwidth on HS bus for " "newly activated TT.\n"); @@ -2404,7 +2404,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, } else { xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Recalculating BW for rootport %u", - virt_dev->real_port); + virt_dev->rhub_port->hw_portnum + 1); } /* Add in how much bandwidth will be used for interval zero, or the @@ -2501,14 +2501,12 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, bw_used += overhead + packet_size; if (!virt_dev->tt_info && virt_dev->udev->speed == USB_SPEED_HIGH) { - unsigned int port_index = virt_dev->real_port - 1; - /* OK, we're manipulating a HS device attached to a * root port bandwidth domain. Include the number of active TTs * in the bandwidth used. */ bw_used += TT_HS_OVERHEAD * - xhci->rh_bw[port_index].num_active_tts; + xhci->rh_bw[virt_dev->rhub_port->hw_portnum].num_active_tts; } xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, @@ -2695,7 +2693,7 @@ void xhci_update_tt_active_eps(struct xhci_hcd *xhci, if (!virt_dev->tt_info) return; - rh_bw_info = &xhci->rh_bw[virt_dev->real_port - 1]; + rh_bw_info = &xhci->rh_bw[virt_dev->rhub_port->hw_portnum]; if (old_active_eps == 0 && virt_dev->tt_info->active_eps != 0) { rh_bw_info->num_active_tts += 1; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6e09b9130fae..634ab517a776 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -739,8 +739,7 @@ struct xhci_virt_device { /* Used for addressing devices and configuration changes */ struct xhci_container_ctx *in_ctx; struct xhci_virt_ep eps[EP_CTX_PER_DEV]; - u8 fake_port; - u8 real_port; + struct xhci_port *rhub_port; struct xhci_interval_bw_table *bw_table; struct xhci_tt_bw_info *tt_info; /* From patchwork Thu Feb 29 14:14:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577169 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B5AC5133987 for ; Thu, 29 Feb 2024 14:13:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215992; cv=none; b=MkhF18Wcnw2c87UxZHW6SeL5UsNx1xnr48L3RPVPS0grUR103H/Qnl8/4PJSmZA8/PPN0Wpbg8UQe5Qk18OhvD2LZcJB2wKakMGloLwhbZ5IVPQ1UenxFoIttcgU7CgTu5MkElrHjltO4N2W911ccVl3WrrG8sAJCmgTGkkk3TQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215992; c=relaxed/simple; bh=egMcKs/5AGhUqO8IiOHkCvShRU2hYYR2V2bry0tk53g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=I4p/9ZoC0aenv+OWFAYZymTTjrwVDTlrAt5WGNXcOGW9iaGoAvIPt5czEbMLbUNNfUA+4ws8FH3VHBFQH4Lemss1dFGvFtz/jKYKneLGIyAFU6iF3CEWWHaijhy6vi/Wcajx97RQwKHYdt5E32ix1lESZy2jA8qA8dLqXToOaFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Tg/JyIJp; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Tg/JyIJp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215991; x=1740751991; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=egMcKs/5AGhUqO8IiOHkCvShRU2hYYR2V2bry0tk53g=; b=Tg/JyIJpHBZcCDIj6rG150l3RfORLdYnIZHDkZtPalhJx0JUhUBgQZXx tSf6gNkDECmPfApgNfoiVIgYIlxlgxUzrbN7KbAaf9s0RzfFyBTszQgZb rvd3g/L49aycJJBZn7xqCu6jUsx2uaWjyUrhhw9Fnzc/2PVOVoHVYsFAa tnPX2fZjknYtZ4kWeTed94t0wY2x1JGfhWMBiUlNw7ulj/a+6G/LK+zGa xAXEyOOLclvdZAOHIzgrn04vXx4fYcMw3wCuEdwS8zV9o30CYKtuA1LkV oFuzY7HbrVgYebTaO6Swl9xP0YSCSLUGkm19DKuyfcTVXIuc3XKzp89MK Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609378" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609378" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:10 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035989" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035989" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:09 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Niklas Neronin , Mathias Nyman Subject: [PATCH 3/9] xhci: save slot ID in struct 'xhci_port' Date: Thu, 29 Feb 2024 16:14:32 +0200 Message-Id: <20240229141438.619372-4-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Niklas Neronin Slot ID is a index of a virtual device in struct 'xhci_hcd->devs[]'. Previously, to get the slot ID associated with a port, we had to loop through all devices and compare ports, which is very inefficient. Instead, the slot ID (of the device which is directly connected to the port), is added to the its corresponding 'xhci_port' struct. As a result, finding the port's device is quick and easy. Function 'xhci_find_slot_id_by_port()' is removed, as it is no longer needed. Signed-off-by: Niklas Neronin Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-hub.c | 71 ++++++------------------------------ drivers/usb/host/xhci-mem.c | 5 +++ drivers/usb/host/xhci-pci.c | 10 ++--- drivers/usb/host/xhci-ring.c | 11 ++---- drivers/usb/host/xhci.h | 4 +- 5 files changed, 26 insertions(+), 75 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 37128a777a58..61f083de6e19 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -448,40 +448,6 @@ u32 xhci_port_state_to_neutral(u32 state) } EXPORT_SYMBOL_GPL(xhci_port_state_to_neutral); -/** - * xhci_find_slot_id_by_port() - Find slot id of a usb device on a roothub port - * @hcd: pointer to hcd of the roothub - * @xhci: pointer to xhci structure - * @port: one-based port number of the port in this roothub. - * - * Return: Slot id of the usb device connected to the root port, 0 if not found - */ - -int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, - u16 port) -{ - int slot_id; - int i; - enum usb_device_speed speed; - - /* 'hcd_portnum' is zero-based, thus convert one-based 'port' to zero-based */ - port -= 1; - slot_id = 0; - for (i = 0; i < MAX_HC_SLOTS; i++) { - if (!xhci->devs[i] || !xhci->devs[i]->udev) - continue; - speed = xhci->devs[i]->udev->speed; - if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3)) - && xhci->devs[i]->rhub_port->hcd_portnum == port) { - slot_id = i; - break; - } - } - - return slot_id; -} -EXPORT_SYMBOL_GPL(xhci_find_slot_id_by_port); - /* * Stop device * It issues stop endpoint command for EP 0 to 30. And wait the last command @@ -932,7 +898,6 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, struct xhci_bus_state *bus_state; struct xhci_hcd *xhci; struct usb_hcd *hcd; - int slot_id; u32 wIndex; hcd = port->rhub->hcd; @@ -988,13 +953,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, spin_lock_irqsave(&xhci->lock, *flags); if (time_left) { - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - wIndex + 1); - if (!slot_id) { + if (!port->slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); return -ENODEV; } - xhci_ring_device(xhci, slot_id); + xhci_ring_device(xhci, port->slot_id); } else { int port_status = readl(port->addr); @@ -1204,7 +1167,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, unsigned long flags; u32 temp, status; int retval = 0; - int slot_id; struct xhci_bus_state *bus_state; u16 link_state = 0; u16 wake_mask = 0; @@ -1334,15 +1296,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; } - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - portnum1); - if (!slot_id) { + if (!port->slot_id) { xhci_warn(xhci, "slot_id is zero\n"); goto error; } /* unlock to execute stop endpoint commands */ spin_unlock_irqrestore(&xhci->lock, flags); - xhci_stop_device(xhci, slot_id, 1); + xhci_stop_device(xhci, port->slot_id, 1); spin_lock_irqsave(&xhci->lock, flags); xhci_set_link_state(xhci, port, XDEV_U3); @@ -1465,14 +1425,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if (link_state == USB_SS_PORT_LS_U3) { int retries = 16; - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - portnum1); - if (slot_id) { + if (port->slot_id) { /* unlock to execute stop endpoint * commands */ spin_unlock_irqrestore(&xhci->lock, flags); - xhci_stop_device(xhci, slot_id, 1); + xhci_stop_device(xhci, port->slot_id, 1); spin_lock_irqsave(&xhci->lock, flags); } xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U3); @@ -1586,13 +1544,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } bus_state->port_c_suspend |= 1 << wIndex; - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - portnum1); - if (!slot_id) { + if (!port->slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); goto error; } - xhci_ring_device(xhci, slot_id); + xhci_ring_device(xhci, port->slot_id); break; case USB_PORT_FEAT_C_SUSPEND: bus_state->port_c_suspend &= ~(1 << wIndex); @@ -1823,10 +1779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) if (!portsc_buf[port_index]) continue; if (test_bit(port_index, &bus_state->bus_suspended)) { - int slot_id; - - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - port_index + 1); + int slot_id = ports[port_index]->slot_id; if (slot_id) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_stop_device(xhci, slot_id, 1); @@ -1879,7 +1832,6 @@ int xhci_bus_resume(struct usb_hcd *hcd) struct xhci_bus_state *bus_state; unsigned long flags; int max_ports, port_index; - int slot_id; int sret; u32 next_state; u32 temp, portsc; @@ -1972,9 +1924,8 @@ int xhci_bus_resume(struct usb_hcd *hcd) continue; } xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC); - slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1); - if (slot_id) - xhci_ring_device(xhci, slot_id); + if (ports[port_index]->slot_id) + xhci_ring_device(xhci, ports[port_index]->slot_id); } (void) readl(&xhci->op_regs->command); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9fa68fa17ac7..c4b3e425bd19 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -907,6 +907,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) if (dev->udev && dev->udev->slot_id) dev->udev->slot_id = 0; + if (dev->rhub_port && dev->rhub_port->slot_id == slot_id) + dev->rhub_port->slot_id = 0; kfree(xhci->devs[slot_id]); xhci->devs[slot_id] = NULL; } @@ -1124,6 +1126,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud dev->rhub_port = xhci_find_rhub_port(xhci, udev); if (!dev->rhub_port) return -EINVAL; + /* Slot ID is set to the device directly below the root hub */ + if (!udev->parent->parent) + dev->rhub_port->slot_id = udev->slot_id; slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(dev->rhub_port->hw_portnum + 1)); xhci_dbg(xhci, "Slot ID %d: HW portnum %d, hcd portnum %d\n", udev->slot_id, dev->rhub_port->hw_portnum, dev->rhub_port->hcd_portnum); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b534ca9752be..1843f3d5b1e6 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -820,7 +820,6 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_port *port; struct usb_device *udev; - unsigned int slot_id; u32 portsc; int i; @@ -843,15 +842,14 @@ static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup) if ((portsc & PORT_PLS_MASK) != XDEV_U3) continue; - slot_id = xhci_find_slot_id_by_port(port->rhub->hcd, xhci, - port->hcd_portnum + 1); - if (!slot_id || !xhci->devs[slot_id]) { + if (!port->slot_id || !xhci->devs[port->slot_id]) { xhci_err(xhci, "No dev for slot_id %d for port %d-%d in U3\n", - slot_id, port->rhub->hcd->self.busnum, port->hcd_portnum + 1); + port->slot_id, port->rhub->hcd->self.busnum, + port->hcd_portnum + 1); continue; } - udev = xhci->devs[slot_id]->udev; + udev = xhci->devs[port->slot_id]->udev; /* if wakeup is enabled then don't disable the port */ if (udev->do_remote_wakeup && do_wakeup) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d4a28ac4967f..95ed26114ee8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1870,7 +1870,6 @@ static void handle_port_status(struct xhci_hcd *xhci, u32 port_id; u32 portsc, cmd_reg; int max_ports; - int slot_id; unsigned int hcd_portnum; struct xhci_bus_state *bus_state; bool bogus_port_status = false; @@ -1922,9 +1921,8 @@ static void handle_port_status(struct xhci_hcd *xhci, if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { - slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); - if (slot_id && xhci->devs[slot_id]) - xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR; + if (port->slot_id && xhci->devs[port->slot_id]) + xhci->devs[port->slot_id]->flags |= VDEV_PORT_ERROR; } if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { @@ -1982,9 +1980,8 @@ static void handle_port_status(struct xhci_hcd *xhci, * so the roothub behavior is consistent with external * USB 3.0 hub behavior. */ - slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); - if (slot_id && xhci->devs[slot_id]) - xhci_ring_device(xhci, slot_id); + if (port->slot_id && xhci->devs[port->slot_id]) + xhci_ring_device(xhci, port->slot_id); if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) { xhci_test_and_clear_bit(xhci, port, PORT_PLC); usb_wakeup_notification(hcd->self.root_hub, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 634ab517a776..6f4bf98a6282 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1462,6 +1462,8 @@ struct xhci_port { unsigned int lpm_incapable:1; unsigned long resume_timestamp; bool rexit_active; + /* Slot ID is the index of the device directly connected to the port */ + int slot_id; struct completion rexit_done; struct completion u3exit_done; }; @@ -1944,8 +1946,6 @@ unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd); #endif /* CONFIG_PM */ u32 xhci_port_state_to_neutral(u32 state); -int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, - u16 port); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); /* xHCI contexts */ From patchwork Thu Feb 29 14:14:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577170 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3545B134CE0 for ; Thu, 29 Feb 2024 14:13:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215993; cv=none; b=daaLZfUM4hPsSbxweJuSTHnEijkOkE68hufS/sVg4IuuGkQ47M5DdNEHSyOG8tKMyiTs94HjC6g45RKDnSMS8wm0hvC/sYcrSY4mc0Ezq5SQuCpi5X/3vTuV2ynadtrRBlg1OI0HhQH5yJ+rZ+MJ035u1xg+/9796orSRxZBHSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215993; c=relaxed/simple; bh=89n19r5KupUpVzKaBY95bg4JqemB4uJxOJX4dx5kJLk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CiqfzXtNNwewZ1c6hH9EAUxnx48g/bq702otlDjGgM0b0cDVd0HV3UgaOxurZBH3ASZIt0O6lPdbQ/EjoYPWmbjQcj+Y5jHII4JtgRsQ7okxJeXuIzvKCUPsqszOsxGl5A2VxYdYFfiamHBjgete0H7pruy9sAy57iEoASl14i4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=YjBqAZpJ; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="YjBqAZpJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215992; x=1740751992; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=89n19r5KupUpVzKaBY95bg4JqemB4uJxOJX4dx5kJLk=; b=YjBqAZpJJzj4OpYSncaQjNq5r+mUmE0HYFhXNhVf+AErRe4VWCR0CdGs ot+0cTXkGPQsd27dDShBTXLnAg2SiSHULaJkk3lw77In6xGVDyXWZvSOK maoo1opVpk/igQ3CkdNXzo91zramHeyRfno4wcLh7xsT2C1lgqcrLs4I1 po5cCmf73j+B+e6SlnCP1YrfX2BDSJPlqUqPsgoDDGDzrA2Q78LZYH/R1 TvW6Ctq4mtwyquaYfH6I2baSjsVmz/BeGP4TtMSMw8eAbQvZ+Eyc34hmA rrxWI6rDHwEnGtL0qkNm9+nOiBX+Se2+7rMzNfSOrgNbq8Iy2Jpf6Bvdm w==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609383" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609383" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:12 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035990" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035990" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:10 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Niklas Neronin , Mathias Nyman Subject: [PATCH 4/9] usb: xhci: remove duplicate code from 'xhci_clear_command_ring()' Date: Thu, 29 Feb 2024 16:14:33 +0200 Message-Id: <20240229141438.619372-5-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Niklas Neronin Replace a segment of code within 'xhci_clear_command_ring()' with a function call to 'xhci_initialize_ring_info()'. This change eliminates code duplication, as 'xhci_initialize_ring_info()' performs the same operations as the replaced code. Signed-off-by: Niklas Neronin Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c50d5881e214..5d70e0176527 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -794,19 +794,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) seg = seg->next; } while (seg != ring->deq_seg); - /* Reset the software enqueue and dequeue pointers */ - ring->deq_seg = ring->first_seg; - ring->dequeue = ring->first_seg->trbs; - ring->enq_seg = ring->deq_seg; - ring->enqueue = ring->dequeue; - - ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1; - /* - * Ring is now zeroed, so the HW should look for change of ownership - * when the cycle bit is set to 1. - */ - ring->cycle_state = 1; - + xhci_initialize_ring_info(ring, 1); /* * Reset the hardware dequeue pointer. * Yes, this will need to be re-written after resume, but we're paranoid From patchwork Thu Feb 29 14:14:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577171 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B9F01353F8 for ; Thu, 29 Feb 2024 14:13:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215995; cv=none; b=GBulqwQ5SqqH7Zf5N6ItIwKgDSoGxU8Z9rjWq+CJYdAsaL2lKbxNwxIxMr/1ZCP8ICcUsZ8egv5LOhUFdhkvOJdAd9C8L1zaFPEjbWSCLZtsA+3QQrBJbbKhw72cCtQGMMA8uJV9nX5AWgMC9hqyI3+4X5ddXDYHwv5X+pMrZ4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215995; c=relaxed/simple; bh=Z6DY0qIGWgmvJ6mAgiD/sc+se094n4EBqRsAcAl9ue0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MTGMo/NGRvtF3i17S0BpCjHRomalSsGUDzeBsVUyLiPgpyjzeZ9zBhqTLKMoCV9/jxqlRFpLMrFpsjnatEYsuNzDDOKzLZGphHEtDkwc0eRNBzKKmebsFwrzhJavEj8vfg90u5+bZvx0/Az0tgHDx5RZL17c8tjaQJbOQXM5xGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=L/P5MMat; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="L/P5MMat" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215994; x=1740751994; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Z6DY0qIGWgmvJ6mAgiD/sc+se094n4EBqRsAcAl9ue0=; b=L/P5MMatJrHXoqiKqjSSIi63BN7aZeNnkeq30kJ5BX44A7tBm2R8EyUj FZOemIGj2CGOKy+JE4c2rt28Vxedz3OJwN6lcXcMPiSnUKJQNc01U8TPd mqyJwYMHqCRtx7rdZHxZK1bxtHZ+jiGV9kjBRCuoeKhTFykUA7ir9eYFX SdQUS+JxrBQMcUPAraes8+KR6wyTHcEjQTQEHc/Cwl9oYM9mGHWq7IAey ToL1urxp5heMHIt+E1SqVe9AdMEq9ccZNKjoSyDs84CIiyc2s96QBgLho PLiVEOBu9aDnKGq4gaeR3GhjD6wV1lfEY5Cb43T66io3Wy+I5ZiLnZO0T w==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609390" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609390" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:14 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035991" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035991" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:12 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Niklas Neronin , Mathias Nyman Subject: [PATCH 5/9] usb: xhci: utilize 'xhci_free_segments_for_ring()' for freeing segments Date: Thu, 29 Feb 2024 16:14:34 +0200 Message-Id: <20240229141438.619372-6-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Niklas Neronin Refactor the code to improve readability by using 'xhci_free_segments_for_ring()' function for freeing ring segments. This replaces the custom while loop previously used within 'xhci_ring_expansion()' and 'xhci_alloc_segments_for_ring()'. Slightly modify 'xhci_free_segments_for_ring()' to handle lists which do not loop. This makes it possible to use it in error paths of 'xhci_alloc_segments_for_ring()'. This change also prepares for switching the custom xhci linked segment list into to more standard list.h lists. [minor commit message rewording -Mathias] Signed-off-by: Niklas Neronin Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-mem.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index c4b3e425bd19..69dd86669883 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -84,7 +84,7 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci, struct xhci_segment *seg; seg = first->next; - while (seg != first) { + while (seg && seg != first) { struct xhci_segment *next = seg->next; xhci_segment_free(xhci, seg); seg = next; @@ -351,17 +351,10 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, next = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags); - if (!next) { - prev = *first; - while (prev) { - next = prev->next; - xhci_segment_free(xhci, prev); - prev = next; - } - return -ENOMEM; - } - xhci_link_segments(prev, next, type, chain_links); + if (!next) + goto free_segments; + xhci_link_segments(prev, next, type, chain_links); prev = next; num++; } @@ -369,6 +362,10 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, *last = prev; return 0; + +free_segments: + xhci_free_segments_for_ring(xhci, *first); + return -ENOMEM; } /* @@ -444,19 +441,11 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, if (ret) return -ENOMEM; - if (ring->type == TYPE_STREAM) + if (ring->type == TYPE_STREAM) { ret = xhci_update_stream_segment_mapping(ring->trb_address_map, ring, first, last, flags); - if (ret) { - struct xhci_segment *next; - do { - next = first->next; - xhci_segment_free(xhci, first); - if (first == last) - break; - first = next; - } while (true); - return ret; + if (ret) + goto free_segments; } xhci_link_rings(xhci, ring, first, last, num_new_segs); @@ -466,6 +455,10 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, ring->num_segs); return 0; + +free_segments: + xhci_free_segments_for_ring(xhci, first); + return ret; } struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, From patchwork Thu Feb 29 14:14:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577172 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC53E134CE0 for ; Thu, 29 Feb 2024 14:13:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215997; cv=none; b=ZTVejcBtgInLzqKGF9wYmMgr0rGa2WlJ9ooLo5MwwZG7quZXts8gCUzg4Gl4H6lh1fqEvj0PMfzVQ2d3gKtV4tiBnTsr/XylxHsA3yG2Z7sPtaue5LM1mPlmAw7ApSd4Vt2UGNAfGG9SkO/cN5zM3CNn4MAkA+kO3yWNRrMXH0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215997; c=relaxed/simple; bh=AiFpotYi6DkxOYrV7id3qofwyLCWC6u3/fvZZDqKzLw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=e35PN1zxrR8g8qyCQfoPFuDahl4kPllVBqoIKezfl+2FfI07GubI9BJzyF70J23KXhalUcfjJzqo1x3ULAms2HZroEqMcArKTlLPRC/zGWxW3Q1Mrdr9r+GWaSl5R4+0oJpX8Lj+7am2wsKvNRNsXIgI3ueXMjoavsBnIdsRro8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=l4fITFqb; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="l4fITFqb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215996; x=1740751996; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AiFpotYi6DkxOYrV7id3qofwyLCWC6u3/fvZZDqKzLw=; b=l4fITFqbf+ME08vLLf/lyDIVZzH++FuUjReT9NYjQacdnIwNwNRxW3Sc 0N07BOyi0xyNX4xWyOD79WkNwQ/qEd+WT0dqfv4B8W5DOeicfWwbsYggr gwUEtk+mLYsU81fHVP8EMcZposOEB8JrQdgom0pI7iy6Zwb8AqCQmecer kqOkASxTbvlhAnWNLkNJG+SrWh/uTZMrh9R6P5uN8s3cc2NQ4KebaK9Oj 2ko/XJ2a7hmySVtwWIxDOYlKLZvIon4Qey6hqBH0V7acF2wB5bsQGlDfD BDoM+z7yIwjHltbkbTqXJsyK2Xl8SUPqUvEodMMAyLw2zkp+zLvXfadZt g==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609395" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609395" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:15 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035992" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035992" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:13 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Michal Pecio , Mathias Nyman Subject: [PATCH 6/9] xhci: fix matching completion events with TDs Date: Thu, 29 Feb 2024 16:14:35 +0200 Message-Id: <20240229141438.619372-7-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Michal Pecio A trb_in_td() call is used to determine if a completion event matches any TRB of the currently executing TD. This function is told to start searching right after the last finished TD, which is not at all where the currently expected TD is guaranteed to begin, because some TDs in between may have been cancelled. Not only is a pointless work performed, but a bug resulting in the HC executing cancelled TDs was seen to trick the driver into associating events from a TD just cancelled with an unrelated future TD. Since the ring is being traversed for the specific purpose of finding a match with the current TD, always start from its first TRB. This is the most reliable bit of information that we posses. Tracking of HC's work progress is not affected, except for cases when a misattributed event would have moved dequeue past a pending TD. Signed-off-by: Michal Pecio Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-ring.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 95ed26114ee8..b2116501048c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2813,7 +2813,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, td_num--; /* Is this a TRB in the currently executing TD? */ - ep_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue, + ep_seg = trb_in_td(xhci, td->start_seg, td->first_trb, td->last_trb, ep_trb_dma, false); /* @@ -2881,9 +2881,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, "part of current TD ep_index %d " "comp_code %u\n", ep_index, trb_comp_code); - trb_in_td(xhci, ep_ring->deq_seg, - ep_ring->dequeue, td->last_trb, - ep_trb_dma, true); + trb_in_td(xhci, td->start_seg, td->first_trb, + td->last_trb, ep_trb_dma, true); return -ESHUTDOWN; } } From patchwork Thu Feb 29 14:14:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577173 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 046191353EF for ; Thu, 29 Feb 2024 14:13:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215998; cv=none; b=eM0942RXXPZ4iSaoqHypJJI4zIAMnxxSjnKhKbBmT0+J1UivHHXq9MrEn56IoRP9yd+1Y4h+DfYh8H57lxeFRRKnQ9pjhRvrdJxz/rj5SC324o18LreWAo4UHs+/sJc0PTyHWqw6/zHjdcdqaoc+jsSWh35UB5YiMSpMAlW/RHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709215998; c=relaxed/simple; bh=hHWeGAQTWPoQXSQAxPUMZKd9yJ0GwYpYZ7JABJrKnrw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UYW801aaPVB/SE4cz2JqSWto37yoA9O9iZeluoedajLTaLYMohJVdGszPUAi3Lku2AUEJ0r+BPbFYRF0Ikj5Y5BRf3Md2EhS1GAY+MVu9fvDz3Or9oGx5CwOlE3mmc5sFFKplcnkD1v3ANGEmd5QZkBzgc2xWUMSuDN+T82Ov98= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GNbfnv/6; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GNbfnv/6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709215997; x=1740751997; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hHWeGAQTWPoQXSQAxPUMZKd9yJ0GwYpYZ7JABJrKnrw=; b=GNbfnv/6iQ8wBO446zcn7du+/pb/H2tttqbo9ZsICozUqtMyjY9w5faM kWtNEar8HhI1+FBO3IZe3a39UTBlhzt09VDJ+mtE18WOqn1Jy5ROK0S1j Fuigv08tRk4xJwjANLP1xnHmdHyvfFrkcM4m3gi7gOJ0b/jZ4kBhQDYeE l3ef8jLJRVAsUzzrubwUQMSf3i8IdFPWPDQ/t5bK9vGbXLk+f156kt2vo tEBiZHKzaTBC6nkmoAf/2UuBC5fFX3UNa326K0jdE3dUu8qLxYScLGUYc ZOSE28kUB0Mf5Br1/7ERxkaK7Ydfo1FktJ5WtWqUp356OjguU5livERAg g==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609402" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609402" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:17 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035993" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035993" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:15 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Michal Pecio , Mathias Nyman Subject: [PATCH 7/9] xhci: retry Stop Endpoint on buggy NEC controllers Date: Thu, 29 Feb 2024 16:14:36 +0200 Message-Id: <20240229141438.619372-8-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Michal Pecio Two NEC uPD720200 adapters have been observed to randomly misbehave: a Stop Endpoint command fails with Context Error, the Output Context indicates Stopped state, and the endpoint keeps running. Very often, Set TR Dequeue Pointer is seen to fail next with Context Error too, in addition to problems from unexpectedly completed cancelled work. The pathology is common on fast running isoc endpoints like uvcvideo, but has also been reproduced on a full-speed bulk endpoint of pl2303. It seems all EPs are affected, with risk proportional to their load. Reproduction involves receiving any kind of stream and closing it to make the device driver cancel URBs already queued in advance. Deal with it by retrying the command like in the Running state. Signed-off-by: Michal Pecio Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-ring.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b2116501048c..6a29ebd6682d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1154,6 +1154,15 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, break; ep->ep_state &= ~EP_STOP_CMD_PENDING; return; + case EP_STATE_STOPPED: + /* + * NEC uPD720200 sometimes sets this state and fails with + * Context Error while continuing to process TRBs. + * Be conservative and trust EP_CTX_STATE on other chips. + */ + if (!(xhci->quirks & XHCI_NEC_HOST)) + break; + fallthrough; case EP_STATE_RUNNING: /* Race, HW handled stop ep cmd before ep was running */ xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n"); From patchwork Thu Feb 29 14:14:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577174 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4DD3412FB29 for ; Thu, 29 Feb 2024 14:13:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709216001; cv=none; b=Xld3pqxBW6mh1ZES7aje1ETekoaQMlyoK8S+ZAxeQfoIIagU2r/60JpGjs4KnYxwww9O8Wn14vpydbYIpq80QKfmIgrnRcRRh0IZn6rr4x9nhV6UxFKpnsuvfJB0scJXSAH7xYfhXT0omkf8W5aMu9bC8M/CzZfC1/bDYflWjKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709216001; c=relaxed/simple; bh=x8njXuX7QPqpTwdtLMXaToyhbmGMPg88HNXHkBcXCHs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HGcpMJFWtJCHtHR+wCpcpRFML9KKAmUC6DNkf0orYbD0NpZsMt5oOreEvILYVtGgP5yHR5V/26Z24rR3lmzwGjJgbFHXEaragn8At3Eaq43cs3PODks3pRF1tqhAIBCKDK1HkABTq1s/+5bxEGzw6pSZ1NqEgYt1umkwEkSdXaU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ZyrXE8RR; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ZyrXE8RR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709216000; x=1740752000; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=x8njXuX7QPqpTwdtLMXaToyhbmGMPg88HNXHkBcXCHs=; b=ZyrXE8RRhP5TRnFdYLF/rjRIkTBaU72v1Sd3LTYPcfGjPNycjwTj5e22 JidIMKKF0txPhf+BvUgGCf0TckUc+Uc6KXPcZnZlVoCIIGtSmFwLgEMNb YJumRBq4UuOxYiNLlPjFKeRZGYFvfegL7jL+YCgHCh2Ld+C129EDfqsGK PLFnha25VqTPpWFiZBqU4QG6Qnv2Ew9C27Qn8a8yJvXm1NrORwv7xJDWw F+2P7/7ac5O1iRMZN4EquZe1dJbZQzFIxrzXFYK92Ow0LL7N01+AczwBC OhTVxAkNVSCBtfkRgSTVTD58BMC7jQG3JTHPLtHNSQcRSFaCJRfqmhnku w==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609406" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609406" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:19 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035996" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035996" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:16 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Mathias Nyman , Uday M Bhat Subject: [PATCH 8/9] xhci: dbc: poll at different rate depending on data transfer activity Date: Thu, 29 Feb 2024 16:14:37 +0200 Message-Id: <20240229141438.619372-9-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 DbC driver starts polling for events immediately when DbC is enabled. The current polling interval is 1ms, which keeps the CPU busy, impacting power management even when there are no active data transfers. Solve this by polling at a slower rate, with a 64ms interval as default until a transfer request is queued, or if there are still are pending unhandled transfers at event completion. Tested-by: Uday M Bhat Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-dbgcap.c | 13 +++++++++++-- drivers/usb/host/xhci-dbgcap.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index d82935d31126..8a9869ef0db6 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -634,7 +634,8 @@ static int xhci_dbc_start(struct xhci_dbc *dbc) return ret; } - return mod_delayed_work(system_wq, &dbc->event_work, 1); + return mod_delayed_work(system_wq, &dbc->event_work, + msecs_to_jiffies(dbc->poll_interval)); } static void xhci_dbc_stop(struct xhci_dbc *dbc) @@ -899,8 +900,10 @@ static void xhci_dbc_handle_events(struct work_struct *work) enum evtreturn evtr; struct xhci_dbc *dbc; unsigned long flags; + unsigned int poll_interval; dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work); + poll_interval = dbc->poll_interval; spin_lock_irqsave(&dbc->lock, flags); evtr = xhci_dbc_do_handle_events(dbc); @@ -916,13 +919,18 @@ static void xhci_dbc_handle_events(struct work_struct *work) dbc->driver->disconnect(dbc); break; case EVT_DONE: + /* set fast poll rate if there are pending data transfers */ + if (!list_empty(&dbc->eps[BULK_OUT].list_pending) || + !list_empty(&dbc->eps[BULK_IN].list_pending)) + poll_interval = 1; break; default: dev_info(dbc->dev, "stop handling dbc events\n"); return; } - mod_delayed_work(system_wq, &dbc->event_work, 1); + mod_delayed_work(system_wq, &dbc->event_work, + msecs_to_jiffies(poll_interval)); } static const char * const dbc_state_strings[DS_MAX] = { @@ -1175,6 +1183,7 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver * dbc->idVendor = DBC_VENDOR_ID; dbc->bcdDevice = DBC_DEVICE_REV; dbc->bInterfaceProtocol = DBC_PROTOCOL; + dbc->poll_interval = DBC_POLL_INTERVAL_DEFAULT; if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE) goto err; diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h index e39e3ae1677a..92661b555c2a 100644 --- a/drivers/usb/host/xhci-dbgcap.h +++ b/drivers/usb/host/xhci-dbgcap.h @@ -94,6 +94,7 @@ struct dbc_ep { #define DBC_QUEUE_SIZE 16 #define DBC_WRITE_BUF_SIZE 8192 +#define DBC_POLL_INTERVAL_DEFAULT 64 /* milliseconds */ /* * Private structure for DbC hardware state: @@ -140,6 +141,7 @@ struct xhci_dbc { enum dbc_state state; struct delayed_work event_work; + unsigned int poll_interval; /* ms */ unsigned resume_required:1; struct dbc_ep eps[2]; From patchwork Thu Feb 29 14:14:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13577175 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18FC912BF22; Thu, 29 Feb 2024 14:13:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709216002; cv=none; b=mJzuy1OA8D9gFXpe08IbRqb9GH2f2gDDhtSSVMr3iTMNT9FFy7SYMXNnjP/Hbfi/b85/lLdifOQx8p3OpxSOdjNsH0KlCWo1KUd+3qePD/NXUCmIcWOVoOtu6BoLg24ZBOmDOJNneFfrT5kOJweU96HPNAGLoEJd8EAhMa+hL/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709216002; c=relaxed/simple; bh=esVJlwSvV9/+UWQnk31M30c2daFC4+WWFpkYBl8pZsQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Kg5ZrjV6wORshvlbYg4KH5Ivm1Wq+893FmCqAz3n+qOYO9z0PVMz6M+5YjQNtg+upUYkw/WSZ1Et6roWPOVgNKbkCYFLVtFBmGWau5RSK1njHgflZ1EgBUpeoXWjXSb9Ec+mhpA6G/71JTmOToObX35ihLTVG7IkOET9zRVuQUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=c2eTOQBh; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="c2eTOQBh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1709216001; x=1740752001; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=esVJlwSvV9/+UWQnk31M30c2daFC4+WWFpkYBl8pZsQ=; b=c2eTOQBhS0pu+mIBlN63sHhof94HPdc+FIrC0E/cwwHHV5Yx+55YdPlq dII3IsblyI2DOQHxKjecEJl+BAJ9lAvdI14yDLQZklEC0r9z57xXC0GA0 59my51kyjuvrdM4lJ5b3/HYBUI+mieXprfRNoYS/WFx7uoHCp/AlVi46i Lhpt4rYddY1K5fQEecu2aY7X+6cq91dJINKbVuEVSFuFj3nH8up9ADLxZ 0RDztRPn8lFNzvR9ZyIi+49WmcDAKEdEs6MncpkXPCZSlpkIxYyVSrK8U idD8zuYSgFwlo1cI8eJkehQt8stZcvwIcoR1FDBoXdAPemty2vbX0lWcs g==; X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="3609412" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="3609412" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Feb 2024 06:13:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10998"; a="937035997" X-IronPort-AV: E=Sophos;i="6.06,194,1705392000"; d="scan'208";a="937035997" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by fmsmga001.fm.intel.com with ESMTP; 29 Feb 2024 06:13:18 -0800 From: Mathias Nyman To: Cc: linux-usb@vger.kernel.org, Prashanth K , stable@vger.kernel.org, Mathias Nyman Subject: [PATCH 9/9] usb: xhci: Add error handling in xhci_map_urb_for_dma Date: Thu, 29 Feb 2024 16:14:38 +0200 Message-Id: <20240229141438.619372-10-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240229141438.619372-1-mathias.nyman@linux.intel.com> References: <20240229141438.619372-1-mathias.nyman@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Prashanth K Currently xhci_map_urb_for_dma() creates a temporary buffer and copies the SG list to the new linear buffer. But if the kzalloc_node() fails, then the following sg_pcopy_to_buffer() can lead to crash since it tries to memcpy to NULL pointer. So return -ENOMEM if kzalloc returns null pointer. Cc: # 5.11 Fixes: 2017a1e58472 ("usb: xhci: Use temporary buffer to consolidate SG") Signed-off-by: Prashanth K Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5d70e0176527..8579603edaff 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1219,6 +1219,8 @@ static int xhci_map_temp_buffer(struct usb_hcd *hcd, struct urb *urb) temp = kzalloc_node(buf_len, GFP_ATOMIC, dev_to_node(hcd->self.sysdev)); + if (!temp) + return -ENOMEM; if (usb_urb_dir_out(urb)) sg_pcopy_to_buffer(urb->sg, urb->num_sgs,