From patchwork Sat Nov 17 01:07:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 10687205 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7406313B5 for ; Sat, 17 Nov 2018 01:08:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63DA42C17A for ; Sat, 17 Nov 2018 01:08:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 57EFB2C1A6; Sat, 17 Nov 2018 01:08:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE54F2C17A for ; Sat, 17 Nov 2018 01:08:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731182AbeKQLXY (ORCPT ); Sat, 17 Nov 2018 06:23:24 -0500 Received: from mail-pg1-f201.google.com ([209.85.215.201]:35877 "EHLO mail-pg1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727116AbeKQLWj (ORCPT ); Sat, 17 Nov 2018 06:22:39 -0500 Received: by mail-pg1-f201.google.com with SMTP id 143so14027741pgc.3 for ; Fri, 16 Nov 2018 17:07:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=3+V0B5HfCmIbS1CGOR3HioePk534q44RYhZtw60V2so=; b=fBEXgzgljW3FCHJH2l0voeT5o3hZ/ZaRfqNSYdcAW0B1SuDjvpNbkT5ZXAO+sIEik3 u71feX4aANzbI/T6FPerx8/tZ3nVYm1NSeGhNOVAUmiuf/D8foByvRyvyz9JDNjeMM74 loSg9aQRCrjTiyZQ6p1Af4D7T8pbu14tlaqnO/BY4UR7pb1jq3K74BqzuCanoZ1sHFIe AVoPSpVDML1GKT2cK1m2txAI14asWc6bxZwSo2O1dCUg7208DUU0V89Bz8o2tV/AiqkI 4iSyTe/31Yy58qLUSnkjFJFU7H9swtknd4Bcv/no5I7npndfnm98j8GuFvys+M9SgGxH F31Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=3+V0B5HfCmIbS1CGOR3HioePk534q44RYhZtw60V2so=; b=BtoBxUBurXA2Miko8/EE28RrXzxns7r05CvkvDdEfDuUMZNtTrR9lmwoCIdqRANKv9 VXYA3GzfOVQ/fM8MWkOaUs7V0hsJNq2erwZBcWgrgUh6SoVWISgvrnvEMvhLfqmmVq94 fdG6Ma6OUvchsrBDgYm7hFGx34nRyE1RDbcSc4l3FG6tV8ZT1VdzArXZJaN+79ehLUKG yLMy9sFdozbX+jSF0jUCfXe5XGHVBryxLkD8kD3npZXBXrtIneWcdmii0g2UvzL91OdM cgfTKWzWejAgTkDCbEG68BsZK5ZBZ7czlOTg7yediqWCSyzppyxKzP0jQbAsfy851f6A sUoA== X-Gm-Message-State: AGRZ1gI4b+P7HvB7YyNF/CPsZNvqvik8SKJa8FE+SbYSp3LbVsm4/gXG 4q9Q63k4k3J6Rzx3XzBiSF78wHf6WND8 X-Google-Smtp-Source: AJdET5dYgDB3ETVvI2sBtTEt31uhe4FlVl2dDpgGlyHkdTKyPft8YWW3ui3Cyh+L3Wj076+23u9sP0mO6vxn X-Received: by 2002:a62:ac0b:: with SMTP id v11mr425852pfe.104.1542416877428; Fri, 16 Nov 2018 17:07:57 -0800 (PST) Date: Fri, 16 Nov 2018 17:07:44 -0800 In-Reply-To: <20181117010748.24347-1-rajatja@google.com> Message-Id: <20181117010748.24347-2-rajatja@google.com> Mime-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> X-Mailer: git-send-email 2.19.1.1215.g8438c0b245-goog Subject: [PATCH 1/5] usb: split code locating ACPI companion into port and device From: Rajat Jain To: Marcel Holtmann , Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Rajat Jain , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dmitry Torokhov In preparation for handling embedded USB devices let's split usb_acpi_find_companion() into usb_acpi_find_companion_for_device() and usb_acpi_find_companion_for_port(). Signed-off-by: Dmitry Torokhov Signed-off-by: Rajat Jain --- drivers/usb/core/usb-acpi.c | 133 +++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 61 deletions(-) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index e221861b3187..8ff73c83e8e8 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -139,12 +139,79 @@ static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent, return acpi_find_child_device(parent, raw, false); } -static struct acpi_device *usb_acpi_find_companion(struct device *dev) +static struct acpi_device * +usb_acpi_get_companion_for_port(struct usb_port *port_dev) { struct usb_device *udev; struct acpi_device *adev; acpi_handle *parent_handle; + int port1; + + /* Get the struct usb_device point of port's hub */ + udev = to_usb_device(port_dev->dev.parent->parent); + + /* + * The root hub ports' parent is the root hub. The non-root-hub + * ports' parent is the parent hub port which the hub is + * connected to. + */ + if (!udev->parent) { + adev = ACPI_COMPANION(&udev->dev); + port1 = usb_hcd_find_raw_port_number(bus_to_hcd(udev->bus), + port_dev->portnum); + } else { + parent_handle = usb_get_hub_port_acpi_handle(udev->parent, + udev->portnum); + if (!parent_handle) + return NULL; + + acpi_bus_get_device(parent_handle, &adev); + port1 = port_dev->portnum; + } + + return usb_acpi_find_port(adev, port1); +} + +static struct acpi_device * +usb_acpi_find_companion_for_port(struct usb_port *port_dev) +{ + struct acpi_device *adev; + struct acpi_pld_info *pld; + acpi_handle *handle; + acpi_status status; + + adev = usb_acpi_get_companion_for_port(port_dev); + if (!adev) + return NULL; + + handle = adev->handle; + status = acpi_get_physical_device_location(handle, &pld); + if (!ACPI_FAILURE(status) && pld) { + port_dev->location = USB_ACPI_LOCATION_VALID + | pld->group_token << 8 | pld->group_position; + port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); + ACPI_FREE(pld); + } + return adev; +} + +static struct acpi_device * +usb_acpi_find_companion_for_device(struct usb_device *udev) +{ + struct acpi_device *adev; + + if (!udev->parent) + return NULL; + + /* root hub is only child (_ADR=0) under its parent, the HC */ + adev = ACPI_COMPANION(udev->dev.parent); + return acpi_find_child_device(adev, 0, false); +} + + +static struct acpi_device *usb_acpi_find_companion(struct device *dev) +{ /* * In the ACPI DSDT table, only usb root hub and usb ports are * acpi device nodes. The hierarchy like following. @@ -158,66 +225,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) * So all binding process is divided into two parts. binding * root hub and usb ports. */ - if (is_usb_device(dev)) { - udev = to_usb_device(dev); - if (udev->parent) - return NULL; - - /* root hub is only child (_ADR=0) under its parent, the HC */ - adev = ACPI_COMPANION(dev->parent); - return acpi_find_child_device(adev, 0, false); - } else if (is_usb_port(dev)) { - struct usb_port *port_dev = to_usb_port(dev); - int port1 = port_dev->portnum; - struct acpi_pld_info *pld; - acpi_handle *handle; - acpi_status status; - - /* Get the struct usb_device point of port's hub */ - udev = to_usb_device(dev->parent->parent); - - /* - * The root hub ports' parent is the root hub. The non-root-hub - * ports' parent is the parent hub port which the hub is - * connected to. - */ - if (!udev->parent) { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - int raw; - - raw = usb_hcd_find_raw_port_number(hcd, port1); - - adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev), - raw); - - if (!adev) - return NULL; - } else { - parent_handle = - usb_get_hub_port_acpi_handle(udev->parent, - udev->portnum); - if (!parent_handle) - return NULL; - - acpi_bus_get_device(parent_handle, &adev); - - adev = usb_acpi_find_port(adev, port1); - - if (!adev) - return NULL; - } - handle = adev->handle; - status = acpi_get_physical_device_location(handle, &pld); - if (ACPI_FAILURE(status) || !pld) - return adev; - - port_dev->location = USB_ACPI_LOCATION_VALID - | pld->group_token << 8 | pld->group_position; - port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); - ACPI_FREE(pld); - - return adev; - } + if (is_usb_device(dev)) + return usb_acpi_find_companion_for_device(to_usb_device(dev)); + else if (is_usb_port(dev)) + return usb_acpi_find_companion_for_port(to_usb_port(dev)); return NULL; } From patchwork Sat Nov 17 01:07:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 10687203 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6ABDD13B5 for ; Sat, 17 Nov 2018 01:08:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5993D2BE82 for ; Sat, 17 Nov 2018 01:08:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4DB9A2BEF7; Sat, 17 Nov 2018 01:08:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C66AA2BE82 for ; Sat, 17 Nov 2018 01:08:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730743AbeKQLWn (ORCPT ); Sat, 17 Nov 2018 06:22:43 -0500 Received: from mail-pl1-f202.google.com ([209.85.214.202]:41901 "EHLO mail-pl1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730277AbeKQLWm (ORCPT ); Sat, 17 Nov 2018 06:22:42 -0500 Received: by mail-pl1-f202.google.com with SMTP id y2so10859484plr.8 for ; Fri, 16 Nov 2018 17:08:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=s3V1He2Zj5wng/11t7K3HEWj/4wZGpXZr3vO1JV3B7s=; b=VoTZcDlK+vJS5EdgLM8TokoaYkl1BgjquuNWLN560DpIJoU8cTccEOBZb0dyCqJwzN 39fteUJOWxdSIDetnAJYERMadSBBhZRFD3fSExO4UQrlWBf8YisCo1zT+5/xtA7GQHLW JefAYZ9XiCf2CIa3Ypzngk4KgvISSKXfv2gtPkCDcIZp9Pumw4a/PziS47Tx5tP0jaiN PPeLBOr0U6oFM6HqQwrdnRkqHFYC1xFqPVGGMZNf+xeKeWtP4JZryYmD2Ka9QR6EOJLL HTyTWHh6QpqmQiO0TaqcKxYDSAWJV4hWgoPuN9YX8oSCjXG1lLCt3RaQD+vHGrYfOeP8 hvsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=s3V1He2Zj5wng/11t7K3HEWj/4wZGpXZr3vO1JV3B7s=; b=DWKIGqg7iBlLWZVCP+tHNsv0wLScPaU2cczGtiF/qmfqJ1oIyDvPg0ANaGY8Fefn+j DSI5Z5DjD/cTBo3ZHcjJmFPHZWqiLBvDX9A8Hr+HXxyr/EpgV0f/XougrywCuIsiudxP IGS2YyFXwoDELv9Th44OPE8a+rPYAQbl7Tun5lOfm2BgDlBF7qZ54JIbQl77rktF6l2f 42SDiFsSewuOWIbh7L6uaHY8GmDCiEgaB3uQHrvyPouhL6b2Q/rNacYL6iMsc8jHmXD3 bB6qvEp9RraIh2xLOUvsalTZ7EyvuvD45+ZJzjvPb7VZUeROCc39TbWd6u4u3+CbSoRD 1R4w== X-Gm-Message-State: AGRZ1gJKd5+gsy2rT/WpEqT8krEGlNANHbc/yFWsJ4bgXfkNAIOS3ita b7ZgeJqBjcQn+LeauKgP8v/iuu7zFX/9 X-Google-Smtp-Source: AJdET5fT21G7Mst65AWLTtqZDKa2Kxm5bUKbPAIVj2Mk2Av80SRcUeA7bJ33k04/S8D3kGmbtP06CQBXFq36 X-Received: by 2002:aa7:8157:: with SMTP id d23-v6mr186165pfn.136.1542416881178; Fri, 16 Nov 2018 17:08:01 -0800 (PST) Date: Fri, 16 Nov 2018 17:07:45 -0800 In-Reply-To: <20181117010748.24347-1-rajatja@google.com> Message-Id: <20181117010748.24347-3-rajatja@google.com> Mime-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> X-Mailer: git-send-email 2.19.1.1215.g8438c0b245-goog Subject: [PATCH 2/5] usb: assign ACPI companions for embedded USB devices From: Rajat Jain To: Marcel Holtmann , Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Rajat Jain , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dmitry Torokhov USB devices permanently connected to USB ports may be described in ACPI tables and share ACPI devices with ports they are connected to. See [1] for details. This will allow us to describe sideband resources for devices, such as, for example, hard reset line for BT USB controllers. [1] https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/other-acpi-namespace-objects#acpi-namespace-hierarchy-and-adr-for-embedded-usb-devices Signed-off-by: Dmitry Torokhov Signed-off-by: Rajat Jain (changed how we get the usb_port) --- drivers/usb/core/usb-acpi.c | 44 +++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 8ff73c83e8e8..9043d7242d67 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -200,30 +200,56 @@ static struct acpi_device * usb_acpi_find_companion_for_device(struct usb_device *udev) { struct acpi_device *adev; + struct usb_port *port_dev; + struct usb_hub *hub; + + if (!udev->parent) { + /* root hub is only child (_ADR=0) under its parent, the HC */ + adev = ACPI_COMPANION(udev->dev.parent); + return acpi_find_child_device(adev, 0, false); + } - if (!udev->parent) + hub = usb_hub_to_struct_hub(udev->parent); + if (!hub) return NULL; - /* root hub is only child (_ADR=0) under its parent, the HC */ - adev = ACPI_COMPANION(udev->dev.parent); - return acpi_find_child_device(adev, 0, false); + /* + * This is an embedded USB device connected to a port and such + * devices share port's ACPI companion. + */ + port_dev = hub->ports[udev->portnum - 1]; + return usb_acpi_get_companion_for_port(port_dev); } - static struct acpi_device *usb_acpi_find_companion(struct device *dev) { /* - * In the ACPI DSDT table, only usb root hub and usb ports are - * acpi device nodes. The hierarchy like following. + * The USB hierarchy like following: + * * Device (EHC1) * Device (HUBN) * Device (PR01) * Device (PR11) * Device (PR12) + * Device (FN12) + * Device (FN13) * Device (PR13) * ... - * So all binding process is divided into two parts. binding - * root hub and usb ports. + * where HUBN is root hub, and PRNN are USB ports and devices + * connected to them, and FNNN are individualk functions for + * connected composite USB devices. PRNN and FNNN may contain + * _CRS and other methods describing sideband resources for + * the connected device. + * + * On the kernel side both root hub and embedded USB devices are + * represented as instances of usb_device structure, and ports + * are represented as usb_port structures, so the whole process + * is split into 2 parts: finding companions for devices and + * finding companions for ports. + * + * Note that we do not handle individual functions of composite + * devices yet, for that we would need to assign companions to + * devices corresponding to USB interfaces. */ if (is_usb_device(dev)) return usb_acpi_find_companion_for_device(to_usb_device(dev)); From patchwork Sat Nov 17 01:07:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 10687201 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0239413B5 for ; Sat, 17 Nov 2018 01:08:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E5AA32BE5D for ; Sat, 17 Nov 2018 01:08:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D891B2BECA; Sat, 17 Nov 2018 01:08:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 74E1D2BE5D for ; Sat, 17 Nov 2018 01:08:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730907AbeKQLWr (ORCPT ); Sat, 17 Nov 2018 06:22:47 -0500 Received: from mail-pg1-f202.google.com ([209.85.215.202]:51885 "EHLO mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730899AbeKQLWr (ORCPT ); Sat, 17 Nov 2018 06:22:47 -0500 Received: by mail-pg1-f202.google.com with SMTP id z13-v6so16646903pgv.18 for ; Fri, 16 Nov 2018 17:08:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=vGykdBl547WQNsa3hHIaJmF/PJ6TocftyqcyGK983ds=; b=Bk0/2DMl06D/t/uR8JTQ4g1fx6IEQ5hmQQYf4mjM5WPed+7xOkh0asmfs5FCU7f+Ho yOUaOt0n7bR5h0MAgFM2kvhwgDzED/W2rYgGU1cebcxSCZf/yz7o2nqXPQn22eB5g4Zh uxMcpw2guzTs/xpn3Eu0fUbrWUURv9U/Xsa6DpV2rHA7POiEENo2FhRxicOozEtNRK/m WejB9wgIeXQuUpDQe3Bv1GHZdrWszM0vvU9/mOR+emMLORcZlRjcfpMgbbGScBBFVgsD tNCP4Y3lTnXDRj3Rxt3wFUH0gDPN+evLbRY3AW/OtjFKZ2DSgN1Sv8PWSF+W3K92i1WN 7VZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=vGykdBl547WQNsa3hHIaJmF/PJ6TocftyqcyGK983ds=; b=GCKhhRxENBCqGxT7a/QiX3tHeotbrtgSc8KPNwWFtMIW5Zq+N6O+aWCpmo2q6afoAZ /ksUGFz9w7uucEgSbrfJXcFUDSWkN+1d2j3WI8j0X7KJMArrlK1x2e7/2XLR3Qa7/ldB K8JTmhRhtMj5VG1Ft/wf4d/akb+w9C0aRnEHxfQWASf48UPl7w5mZGUG/QTFEo5Zersg grN1mWci7jXyYLWOIgnWUVq2Ku5+SDMYSdfDCpz21j8SIFqoYsHbA+SutOH2M5Hm8Q0V FFkbFmUrG8p4d/Fpedq4eP8vy6KX4m1vVEUiUuAyFZB9JcQGI5uhDyPhXJHhjWNn8QCB R9VQ== X-Gm-Message-State: AA+aEWbqSehNg5/e0yFLBXRhwcSXBve/ISDYPVLYqIPUETHtuBCidZci y5tv4l1HTYerr+xEZ8Ewl8oDh/WvzUx7 X-Google-Smtp-Source: AFSGD/XNrAd5Rq1HC2xEdE2LNbI4si4DUeI/pAMxIF3yhPUtPyeWue/gqDzlLPxo3Yac8uZgNPCcsmYY1qpJ X-Received: by 2002:a63:5fd6:: with SMTP id t205mr51086pgb.77.1542416885652; Fri, 16 Nov 2018 17:08:05 -0800 (PST) Date: Fri, 16 Nov 2018 17:07:46 -0800 In-Reply-To: <20181117010748.24347-1-rajatja@google.com> Message-Id: <20181117010748.24347-4-rajatja@google.com> Mime-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> X-Mailer: git-send-email 2.19.1.1215.g8438c0b245-goog Subject: [PATCH 3/5] Bluetooth: Reset Bluetooth chip after multiple command timeouts From: Rajat Jain To: Marcel Holtmann , Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Rajat Jain , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a quirk and a hook to allow the HCI core to reset the BT chip if needed (after a number of timed out commands). Use that new hook to initiate BT chip reset if the controller fails to respond to certain number of commands (currently 5) including the HCI reset commands. This is done based on a newly introduced quirk. This is done based on some initial work by Intel. Signed-off-by: Rajat Jain --- include/net/bluetooth/hci.h | 8 ++++++++ include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c36dc1e20556..af02fa5ffe54 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -192,6 +192,14 @@ enum { * */ HCI_QUIRK_NON_PERSISTENT_SETUP, + + /* When this quirk is set, hw_reset() would be run to reset the + * hardware, after a certain number of commands (currently 5) + * time out because the device fails to respond. + * + * This quirk should be set before hci_register_dev is called. + */ + HCI_QUIRK_HW_RESET_ON_TIMEOUT, }; /* HCI device flags */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e5ea633ea368..b86218304b80 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -313,6 +313,7 @@ struct hci_dev { unsigned int acl_cnt; unsigned int sco_cnt; unsigned int le_cnt; + unsigned int timeout_cnt; unsigned int acl_mtu; unsigned int sco_mtu; @@ -437,6 +438,7 @@ struct hci_dev { int (*post_init)(struct hci_dev *hdev); int (*set_diag)(struct hci_dev *hdev, bool enable); int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr); + void (*hw_reset)(struct hci_dev *hdev); }; #define HCI_PHY_HANDLE(handle) (handle & 0xff) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7352fe85674b..ab3a6a8b7ba6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2569,13 +2569,24 @@ static void hci_cmd_timeout(struct work_struct *work) struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_timer.work); + hdev->timeout_cnt++; if (hdev->sent_cmd) { struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; u16 opcode = __le16_to_cpu(sent->opcode); - bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode); + bt_dev_err(hdev, "command 0x%4.4x tx timeout (cnt = %u)", + opcode, hdev->timeout_cnt); } else { - bt_dev_err(hdev, "command tx timeout"); + bt_dev_err(hdev, "command tx timeout (cnt = %u)", + hdev->timeout_cnt); + } + + if (test_bit(HCI_QUIRK_HW_RESET_ON_TIMEOUT, &hdev->quirks) && + hdev->timeout_cnt >= 5) { + hdev->timeout_cnt = 0; + if (hdev->hw_reset) + hdev->hw_reset(hdev); + return; } atomic_set(&hdev->cmd_cnt, 1); From patchwork Sat Nov 17 01:07:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 10687197 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 55F821709 for ; Sat, 17 Nov 2018 01:08:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D7DF2C9EC for ; Sat, 17 Nov 2018 01:08:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 08CDF2CA0F; Sat, 17 Nov 2018 01:08:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 97B192C9EC for ; Sat, 17 Nov 2018 01:08:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731018AbeKQLWv (ORCPT ); Sat, 17 Nov 2018 06:22:51 -0500 Received: from mail-pg1-f201.google.com ([209.85.215.201]:53595 "EHLO mail-pg1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731017AbeKQLWu (ORCPT ); Sat, 17 Nov 2018 06:22:50 -0500 Received: by mail-pg1-f201.google.com with SMTP id h10so14275760pgv.20 for ; Fri, 16 Nov 2018 17:08:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=otj/32ePMtp8zjyI9T3AOMCzqrhYC3AtvdJgM2y5xMU=; b=KRJ9ktXtxL92PTIPjGraoP+jZH+QxfyrW0XLo5P38qqRG5iXW4H0mbHVGrTJY01VVY 5IQkgkU8oE7auKOf1UjR0ex9sDUtY3z6klXTaGvBm6z7jZ31hwKDLIfkIsCIGqQLj3qJ rRQYBIWTdtCd8UERr8EnmPR8+st0jufTbj853h8ul+nW3py4ooVTOUZYjzDRQH0jVfRn p3g5E2BWinWrcvlh8ET0/PqZW6pjQIdslKm93VXTCiau0BoZ2VXfgsofdeAMYzID9YTD 07wb0FyHo6ZoJbIitMBhVaRKA0IfzjCQqu/ZtOzyLQPfcA35pHFgJXLSJcfCrIRIhz5r 9BVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=otj/32ePMtp8zjyI9T3AOMCzqrhYC3AtvdJgM2y5xMU=; b=AqPjmPRgcrUnLuOSH4LOpDso1o7ClKPB6HHsi4tY78RmtJr+Km1mqy8p80V7JwZ2hX 7/iUf1UiRiHmUg9yMP+sfFfCOEcYK7tuX7ce2sfdCmgSjTeaES42Uq1n1vp2pq/IwfNp aramcTtbIPAWMVSkVGlkzIQhH6N7xbOv2AatwM7aEHS5R3HuWhohyOl6Lbf8161L8WGm iu2wawMZsWXwGPvnTkaeH8pOVl4b/i9EzFMEfxpisB/eVcUqklWrES/y6nZgfAESiM4v sxFWmQqB81PYgKX2TkEmUiaqrcz/a7avacBkuqvQWJYTkq1XZc+X5Yb8JmQX6HlmzX66 9gEA== X-Gm-Message-State: AA+aEWa8c5TteIGPQfM3/1x3Jg9fwJL+H0IXUs7sLmJYXfMeMYtS6o8J YZUet0u5t+ZSbJJhVnsKGuwyXS9+LWkO X-Google-Smtp-Source: AFSGD/XRJZoMm/pkhIcQK8n1ROMyqQENtXD0+5hcPxiq6+KXNTzOQ3LxFLcqSj/FLV/zvuQs2WbLKtVsxm0m X-Received: by 2002:a63:e210:: with SMTP id q16mr64085pgh.132.1542416889258; Fri, 16 Nov 2018 17:08:09 -0800 (PST) Date: Fri, 16 Nov 2018 17:07:47 -0800 In-Reply-To: <20181117010748.24347-1-rajatja@google.com> Message-Id: <20181117010748.24347-5-rajatja@google.com> Mime-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> X-Mailer: git-send-email 2.19.1.1215.g8438c0b245-goog Subject: [PATCH 4/5] Bluetooth: btusb: Collect the common Intel assignments together From: Rajat Jain To: Marcel Holtmann , Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Rajat Jain , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The BTUSB_INTEL and BTUSB_INTEL_NEW have common functions & quirks are assigned to hdev structure. Lets collect them together instead of repeating them in different code branches. Signed-off-by: Rajat Jain --- drivers/bluetooth/btusb.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7439a7eb50ac..e8e148480c91 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3077,28 +3077,25 @@ static int btusb_probe(struct usb_interface *intf, data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2); } #endif + if (id->driver_info & BTUSB_INTEL || + id->driver_info & BTUSB_INTEL_NEW) { - if (id->driver_info & BTUSB_INTEL) { hdev->manufacturer = 2; - hdev->setup = btusb_setup_intel; - hdev->shutdown = btusb_shutdown_intel; - hdev->set_diag = btintel_set_diag_mfg; hdev->set_bdaddr = btintel_set_bdaddr; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); - } - if (id->driver_info & BTUSB_INTEL_NEW) { - hdev->manufacturer = 2; - hdev->send = btusb_send_frame_intel; - hdev->setup = btusb_setup_intel_new; - hdev->hw_error = btintel_hw_error; - hdev->set_diag = btintel_set_diag; - hdev->set_bdaddr = btintel_set_bdaddr; - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); + if (id->driver_info & BTUSB_INTEL) { + hdev->setup = btusb_setup_intel; + hdev->shutdown = btusb_shutdown_intel; + hdev->set_diag = btintel_set_diag_mfg; + } else { + hdev->send = btusb_send_frame_intel; + hdev->setup = btusb_setup_intel_new; + hdev->hw_error = btintel_hw_error; + hdev->set_diag = btintel_set_diag; + } } if (id->driver_info & BTUSB_MARVELL) From patchwork Sat Nov 17 01:07:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 10687199 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0C7D813B5 for ; Sat, 17 Nov 2018 01:08:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE71C2C9EC for ; Sat, 17 Nov 2018 01:08:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD3822CA0F; Sat, 17 Nov 2018 01:08:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 66D502C9EC for ; Sat, 17 Nov 2018 01:08:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731113AbeKQLXB (ORCPT ); Sat, 17 Nov 2018 06:23:01 -0500 Received: from mail-qk1-f202.google.com ([209.85.222.202]:34152 "EHLO mail-qk1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731006AbeKQLXA (ORCPT ); Sat, 17 Nov 2018 06:23:00 -0500 Received: by mail-qk1-f202.google.com with SMTP id k66so55700123qkf.1 for ; Fri, 16 Nov 2018 17:08:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=9Bz/gCkqSI0CecCt2g4/WTM1AOdDeQtvlngMweYYdmw=; b=nlgihIctGCne0mtlEThgsyUWNHtbhJpNh7Z49gDzmEhVdo/LQZm/OA/XsS3egMZ8FK G4chD8RmD72ekB+dcMRvjugvKGX0znbKqtkm69Ne0nKmGG0+0cLvlLb+Enzkwktv78+r +rqn5i+5tKs9Y5IvgtzuOQgqQQXY6NtRE96pr5NYtSMjsUhVH7giRhp+p/r0D/UgHkuI vV96C+IVoEiXhIZBO4pMTLfRRduH1miJBg8vIgkNV1t3KiQ5JXBYEgz/5qYYs+hL1djj eblAGBCjApClh1JtV7aC+fpNL04w0O72N+v3E9BigjIkCNoqPjyc/GFnZZY9imJxjIyi gF8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=9Bz/gCkqSI0CecCt2g4/WTM1AOdDeQtvlngMweYYdmw=; b=J+TtieHO0zANic56UK48A0/rBHQ3l8Wzx9PD0zn8FzvUAcuvANMItvudMWMl6mx7NF 5iBjsJMXIrvlJPAbz/uXZ85QtVSVFx5jFJNmtxeK1c682Js53Stej9dfnINr0ESpKtyo yZjUI9Mw/owBrag2TU5+u3ztkFsNgqvIGQs/AkVR/JivCO/sl8v5rMApas6JhItCfrGj IqA7BEoUMpDD28HNQYo2v0NyB/q271OjKSh8CR1kkflRlLVqI9OnyHEVPtMr3FOb3mej ZCIw7PbvI+kRAoetuU6IETzl0GZ7X3yJPj2EM8VT8OUyYXFFKuCk9POAhARWwzSZusQL 8VYw== X-Gm-Message-State: AA+aEWb8OxXkZT2G75aNqFytTi+uGazwe/343qMk/xUF1Ws+yS4I5Yxv 7hlcAWxXqcyJGTH5/r8XKp81RiVRsjUq X-Google-Smtp-Source: AJdET5cv9bDoi1wGJAXcfLMtIHhqtws0JIoFPYKrXO1shBaaUzv1dsbUlXe3IOo1/i/vZTgPNyoTUETi1XLA X-Received: by 2002:a37:fcd:: with SMTP id 74mr5130365qkp.11.1542416899291; Fri, 16 Nov 2018 17:08:19 -0800 (PST) Date: Fri, 16 Nov 2018 17:07:48 -0800 In-Reply-To: <20181117010748.24347-1-rajatja@google.com> Message-Id: <20181117010748.24347-6-rajatja@google.com> Mime-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> X-Mailer: git-send-email 2.19.1.1215.g8438c0b245-goog Subject: [PATCH 5/5] Bluetooth: btusb: Use the hw_reset method to allow resetting the BT chip From: Rajat Jain To: Marcel Holtmann , Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Rajat Jain , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If the platform provides it, use the reset gpio to reset the BT chip (requested by the HCI core if needed). This has been found helpful on some of Intel bluetooth controllers where the firmware gets stuck and the only way out is a hard reset pin provided by the platform. Signed-off-by: Rajat Jain --- drivers/bluetooth/btusb.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e8e148480c91..8aad02d9e211 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -475,6 +476,8 @@ struct btusb_data { struct usb_endpoint_descriptor *diag_tx_ep; struct usb_endpoint_descriptor *diag_rx_ep; + struct gpio_desc *reset_gpio; + __u8 cmdreq_type; __u8 cmdreq; @@ -490,6 +493,28 @@ struct btusb_data { int oob_wake_irq; /* irq for out-of-band wake-on-bt */ }; + +static void btusb_hw_reset(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct gpio_desc *reset_gpio = data->reset_gpio; + + /* + * Toggle the hard reset line if the platform provides one. The reset + * is going to yank the device off the USB and then replug. So doing + * once is enough. The cleanup is handled correctly on the way out + * (standard USB disconnect), and the new device is detected cleanly + * and bound to the driver again like it should be. + */ + if (reset_gpio) { + bt_dev_dbg(hdev, "%s: Initiating HW reset via gpio", __func__); + clear_bit(HCI_QUIRK_HW_RESET_ON_TIMEOUT, &hdev->quirks); + gpiod_set_value(reset_gpio, 1); + mdelay(100); + gpiod_set_value(reset_gpio, 0); + } +} + static inline void btusb_free_frags(struct btusb_data *data) { unsigned long flags; @@ -3030,6 +3055,11 @@ static int btusb_probe(struct usb_interface *intf, SET_HCIDEV_DEV(hdev, &intf->dev); + data->reset_gpio = gpiod_get_optional(&data->udev->dev, "reset", + GPIOD_OUT_LOW); + if (data->reset_gpio) + hdev->hw_reset = btusb_hw_reset; + hdev->open = btusb_open; hdev->close = btusb_close; hdev->flush = btusb_flush; @@ -3085,6 +3115,7 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); + set_bit(HCI_QUIRK_HW_RESET_ON_TIMEOUT, &hdev->quirks); if (id->driver_info & BTUSB_INTEL) { hdev->setup = btusb_setup_intel; @@ -3225,6 +3256,8 @@ static int btusb_probe(struct usb_interface *intf, return 0; out_free_dev: + if (data->reset_gpio) + gpiod_put(data->reset_gpio); hci_free_dev(hdev); return err; } @@ -3268,6 +3301,9 @@ static void btusb_disconnect(struct usb_interface *intf) if (data->oob_wake_irq) device_init_wakeup(&data->udev->dev, false); + if (data->reset_gpio) + gpiod_put(data->reset_gpio); + hci_free_dev(hdev); }