Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2401363imu; Thu, 24 Jan 2019 12:07:50 -0800 (PST) X-Google-Smtp-Source: ALg8bN6WjoN+UYEz9lcYYEVATeLtcCjryDTes0I326p8gUtC/DJBtFkQJzxbCyy7bRj4k8vT3Yga X-Received: by 2002:a63:a064:: with SMTP id u36mr7295549pgn.145.1548360470763; Thu, 24 Jan 2019 12:07:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548360470; cv=none; d=google.com; s=arc-20160816; b=IuadHtJavs/UQhKhHqMfCEiqHHHNAza2qbYb3TfP5DZTYomeBDA8NwpnEcXYQLaGpJ Ky+UTUFWmOzTbrkDpC54j3b+dZYfLSCiin/wW7myazPJn86ugdK2dmD6M0Ti9z+Zf67G MttoNrUVJWUDfp53T8jHFy7KgwAb0T1GRjGs+uSyaN0sjMyHcVEhew3ifs0TvWomZktE crVMCPeMBhvQNQ4g1PRPi+n9d+rMGTo7ngL5hB8EwchLsqAuFryxTj+uE6ThVls+Yr4u 2tSkxJPKQQYSy1gAS0NU693P20BMZ6EKBAgrsRFINInzh2I3qTmKc+hbxW79qEPuhBN2 dkiA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=I44R5by7utG/5Cuuk2f4UjloCvOrI5Cx4uHif7F31LM=; b=akb2w4Um3DGqDlaqK4j8RXsoWyUau81Bm7iSPrCAKE1pIqVg5dbKR1TXmUabHXKTY6 xxzshbyykvmidME186V/5Im+2QUXRT3Saa+gIrEvYrC6CeLrmdUxNTuVOsVW4WbBliYS s/aZYmW8kCDv8VgRjViU63T4/vqcXcv5FyuAnIMfdmre0k+XlPX6YIhxR/J2FNT66qtL ucR29UNev3M4YyxshtZk7ypKdqjzOyLgUTQYlCvIzk8OzST2MQzn9Sxw0/N/m27vjBSI kVrcP5K20Ji+HKwcmkTHtTQ0Ty0g06uyzz6GqTI0UA/wegQjmcYwuoNZr8tMMC87OHr3 A2uQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=qm9Oxp+Y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33si21610246plt.228.2019.01.24.12.07.35; Thu, 24 Jan 2019 12:07:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=qm9Oxp+Y; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731045AbfAXUGQ (ORCPT + 99 others); Thu, 24 Jan 2019 15:06:16 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:46307 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729034AbfAXUGP (ORCPT ); Thu, 24 Jan 2019 15:06:15 -0500 Received: by mail-lf1-f67.google.com with SMTP id f5so5225217lfc.13 for ; Thu, 24 Jan 2019 12:06:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=I44R5by7utG/5Cuuk2f4UjloCvOrI5Cx4uHif7F31LM=; b=qm9Oxp+YgeCHc1SPFddkkVXbLPcQA58VtGcIQX69gDDtCze6TffAljuOoLBpIWn39m L+vDe15nPgYpyUBDmzofGFpEfHWmhIfjvi/N+qzmFEbcwWkXPtOC2AKKrviBu6TIRxhs 8kikYHtFba+h+efHg1qZHwQR1qEOYEDxnI1QrqEoLv4Fyx7wgi9ENX9QcoY1+XXPAoNc fakQo59z59q6hNznEDPQvlFSn7iB7KIhQlYEezhQ9LV4m7ozdXXe27w6WhHq7tpi3KJK zU9Wwrt7jWH+v1q9uvH3pT7XGqVMSpzh4uor0Aqp43z7PYFGIJ2SWxF2pYC18dgaciCi c+wQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=I44R5by7utG/5Cuuk2f4UjloCvOrI5Cx4uHif7F31LM=; b=ChNgeCADJqrhOBTe2U4RxHOp2vJGdYa2DcUQ1Dztcc2OaAdzKaZmYpZawAialG0QVV r4ppecL6QMp+mz+Z+wCKeD3/7OoGHTbXbObPqcckKKfyFNXoc/ecahCZov3Y8kmw35xq 8Z9VVsx7l7BL6myBTI5lUF1fEXg1h8sYhHsF5MdpTBEMcJIbJ0wV8O/umSBrn0/EvXz8 7x8fM6oZplJck/RbHQpUe2xZ0WdJ4iH/RjXZo9oFfcKfStl0I3JbZ05lyaMwfjXvL2lm a8926l5q9eREn7BIOOjHNWiXZ7EMUSKVcbQ6PJRUwZx4Nf0DlC7nXwYreNfmKSaE1vmP dOtg== X-Gm-Message-State: AJcUukc7+0Wuo8m0CbWOCL+sKQB8WSHuXikywCf4AojM15aqF7TcUL5s bTvtF2HH0W1PsPZ5JUjcOjw25BfeuzIM1IsKsU3V0Q== X-Received: by 2002:a19:2906:: with SMTP id p6mr6259390lfp.17.1548360372533; Thu, 24 Jan 2019 12:06:12 -0800 (PST) MIME-Version: 1.0 References: <20181117010748.24347-1-rajatja@google.com> <20190123205725.239661-1-rajatja@google.com> <20190123205725.239661-4-rajatja@google.com> <7A112914-5B41-4D26-807B-021B7AC907C6@holtmann.org> In-Reply-To: <7A112914-5B41-4D26-807B-021B7AC907C6@holtmann.org> From: Rajat Jain Date: Thu, 24 Jan 2019 12:05:35 -0800 Message-ID: Subject: Re: [PATCH v5 4/4] Bluetooth: btusb: Use the cmd_timeout method to reset the Intel BT chip To: Marcel Holtmann Cc: Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Alex Hung , Bluez mailing list , Linux Kernel Mailing List , linux-usb@vger.kernel.org, netdev , Rajat Jain , Dmitry Torokhov , Raghuram Hegde , chethan.tumkur.narayan@intel.com, "Ghorai, Sukumar" Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Jan 24, 2019 at 1:46 AM Marcel Holtmann wrote= : > > Hi Rajat, > > > If the platform provides it, use the reset gpio to reset the Intel BT > > chip, as part of cmd_timeout handling. This has been found helpful on > > 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 > > --- > > v5: Rename the hook to cmd_timeout, and wait for 5 timeouts before > > resetting the device. > > v4: Use data->flags instead of clearing the quirk in btusb_hw_reset() > > v3: Better error handling for gpiod_get_optional() > > v2: Handle the EPROBE_DEFER case. > > > > drivers/bluetooth/btusb.c | 54 +++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 54 insertions(+) > > > > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c > > index 4761499db9ee..8949ea30a1bc 100644 > > --- a/drivers/bluetooth/btusb.c > > +++ b/drivers/bluetooth/btusb.c > > @@ -29,6 +29,7 @@ > > #include > > #include > > #include > > +#include > > #include > > > > #include > > @@ -439,6 +440,7 @@ static const struct dmi_system_id btusb_needs_reset= _resume_table[] =3D { > > #define BTUSB_BOOTING 9 > > #define BTUSB_DIAG_RUNNING 10 > > #define BTUSB_OOB_WAKE_ENABLED 11 > > +#define BTUSB_HW_RESET_ACTIVE 12 > > > > struct btusb_data { > > struct hci_dev *hdev; > > @@ -476,6 +478,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; > > > > @@ -489,8 +493,39 @@ struct btusb_data { > > int (*setup_on_usb)(struct hci_dev *hdev); > > > > int oob_wake_irq; /* irq for out-of-band wake-on-bt */ > > + unsigned num_cmd_timeout; > > Make this cmd_timeout_count or cmd_timeout_cnt. Sure, will do. > > > }; > > > > + > > +static void btusb_intel_cmd_timeout(struct hci_dev *hdev, > > + struct hci_command_hdr *cmd) > > +{ > > + struct btusb_data *data =3D hci_get_drvdata(hdev); > > + struct gpio_desc *reset_gpio =3D data->reset_gpio; > > + > > + bt_dev_err(hdev, "btusb num_cmd_timeout =3D %u", ++data->num_cmd_= timeout); > > I would prefer if you don=E2=80=99t do the increase in the bt_dev_err(). = And you can also scrap the =E2=80=9Cbtusb =E2=80=9C prefix here since that = is all present via bt_dev_err if really needed at some point. Actually I qu= estion the whole bt_dev_err here in the first place since the core will put= our the error. You are just repeating it here. will do. > > > + > > + if (data->num_cmd_timeout < 5) > > + return; > > So I would propose to do just this: > > if (++data->cmd_timeout_count < 5) > return; will do. > > > + > > + /* > > + * Toggle the hard reset line if the platform provides one. The r= eset > > + * is going to yank the device off the USB and then replug. So do= ing > > + * once is enough. The cleanup is handled correctly on the way ou= t > > + * (standard USB disconnect), and the new device is detected clea= nly > > + * and bound to the driver again like it should be. > > + */ > > + if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { > > + bt_dev_err(hdev, "last reset failed? Not resetting again"= ); > > + return; > > + } > > + > > + bt_dev_err(hdev, "Initiating HW reset via gpio"); > > + 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; > > @@ -2915,6 +2950,7 @@ static int btusb_probe(struct usb_interface *intf= , > > const struct usb_device_id *id) > > { > > struct usb_endpoint_descriptor *ep_desc; > > + struct gpio_desc *reset_gpio; > > struct btusb_data *data; > > struct hci_dev *hdev; > > unsigned ifnum_base; > > @@ -3028,6 +3064,15 @@ static int btusb_probe(struct usb_interface *int= f, > > > > SET_HCIDEV_DEV(hdev, &intf->dev); > > > > + reset_gpio =3D gpiod_get_optional(&data->udev->dev, "reset", > > + GPIOD_OUT_LOW); > > Any reason to not use the devm_gpiod_get_optional() version here? Yes, we're using the &data->udev->dev device (parent of the USB interface) to fetch the gpio, so if we use the devm_* variant, the gpio resource will not be freed immediately if the btusb_probe fails. I'll add a comment in the code to make this more clear. > > > + if (IS_ERR(reset_gpio)) { > > + err =3D PTR_ERR(reset_gpio); > > + goto out_free_dev; > > + } else if (reset_gpio) { > > + data->reset_gpio =3D reset_gpio; > > + } > > + > > hdev->open =3D btusb_open; > > hdev->close =3D btusb_close; > > hdev->flush =3D btusb_flush; > > @@ -3085,6 +3130,8 @@ 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); > > + if (data->reset_gpio) > > + hdev->cmd_timeout =3D btusb_intel_cmd_timeout; > > } > > Always assign hdev->cmd_timeout =3D btusb_intel_cmd_timeout and put it af= ter btintel_set_bdaddr and before the quirks. will do. > > Move the if (data->reset_gpio) check into btusb_intel_cmd_timeout() funct= ion and print a warning that no reset GPIO is present. There'll be Intel platforms already out there which will obviously not have the reset pin described in the ACPI as of today. So I'm not sure if it is right for all of them to start complaining about a missing "reset gpio" in case of timeout post this change. Thus I would prefer to assign hdev->cmd_timeout only if ACPI does provide a gpio i.e. newer platforms that want to support this feature. Thoughts? Thanks, Rajat > > > > > if (id->driver_info & BTUSB_INTEL_NEW) { > > @@ -3097,6 +3144,8 @@ 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); > > + if (data->reset_gpio) > > + hdev->cmd_timeout =3D btusb_intel_cmd_timeout; > > } > > > > if (id->driver_info & BTUSB_MARVELL) > > @@ -3226,6 +3275,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; > > } > > @@ -3269,6 +3320,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); > > } > > Regards > > Marcel >